Skip to content

Project metadata rework #185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions mergin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,15 +519,7 @@ def create_project_and_push(self, project_name, directory, is_public=False, name
self.create_project(project_name, is_public)
if directory:
project_info = self.project_info(project_name)
MerginProject.write_metadata(
directory,
{
"name": project_name,
"version": "v0",
"files": [],
"project_id": project_info["id"],
},
)
MerginProject.write_metadata(directory, project_info)
mp = MerginProject(directory)
if mp.inspect_files():
self.push_project(directory)
Expand Down
19 changes: 2 additions & 17 deletions mergin/client_pull.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,7 @@ def download_project_finalize(job):
task.apply(job.directory, job.mp)

# final update of project metadata
# TODO: why not exact copy of project info JSON ?
job.mp.update_metadata(
{
"name": job.project_path,
"version": job.version,
"project_id": job.project_info["id"],
"files": job.project_info["files"],
}
)
job.mp.update_metadata(job.project_info)


def download_project_cancel(job):
Expand Down Expand Up @@ -613,14 +605,7 @@ def pull_project_finalize(job):
job.mp.log.info("--- pull aborted")
raise ClientError("Failed to apply pull changes: " + str(e))

job.mp.update_metadata(
{
"name": job.project_path,
"version": job.version if job.version else "v0", # for new projects server version is ""
"project_id": job.project_info["id"],
"files": job.project_info["files"],
}
)
job.mp.update_metadata(job.project_info)

if job.mp.has_unfinished_pull():
job.mp.log.info("--- failed to complete pull -- project left in the unfinished pull state")
Expand Down
9 changes: 1 addition & 8 deletions mergin/client_push.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,7 @@ def push_project_finalize(job):
job.mp.log.info("cancel response: " + str(err2))
raise err

job.mp.update_metadata(
{
"name": job.project_path,
"version": job.server_resp["version"],
"project_id": job.server_resp["id"],
"files": job.server_resp["files"],
}
)
job.mp.update_metadata(job.server_resp)
try:
job.mp.apply_push_changes(job.changes)
except Exception as e:
Expand Down
27 changes: 24 additions & 3 deletions mergin/merginproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def __init__(self, directory):

# metadata from JSON are lazy loaded
self._metadata = None
self.is_old_metadata = False

self.setup_logging(directory)

Expand Down Expand Up @@ -139,7 +140,10 @@ def project_full_name(self) -> str:
"""Returns fully qualified project name: <workspace>/<name>"""
if self._metadata is None:
self._read_metadata()
return self._metadata["name"]
if self.is_old_metadata:
return self._metadata["name"]
else:
return f"{self._metadata['namespace']}/{self._metadata['name']}"

def project_name(self) -> str:
"""Returns only project name, without its workspace name"""
Expand All @@ -154,10 +158,25 @@ def workspace_name(self) -> str:
return full_name[:slash_index]

def project_id(self) -> str:
"""Returns ID of the project (UUID using 8-4-4-4-12 formatting without braces)"""
"""Returns ID of the project (UUID using 8-4-4-4-12 formatting without braces)

Raises ClientError if project id is not present in the project metadata. This should
only happen with projects downloaded with old client, before February 2023,
see https://github.com/MerginMaps/mergin-py-client/pull/154
"""
if self._metadata is None:
self._read_metadata()
return self._metadata["project_id"]

# "id" or "project_id" may not exist in projects downloaded with old client version
if self.is_old_metadata:
if "project_id" not in self._metadata:
raise ClientError(
"The project directory has been created with an old version of the Mergin Maps client. "
"Please delete the project directory and re-download the project."
)
return self._metadata["project_id"]
else:
return self._metadata["id"]

def workspace_id(self) -> int:
"""Returns ID of the workspace where the project belongs"""
Expand Down Expand Up @@ -196,6 +215,8 @@ def _read_metadata(self):
with open(self.fpath_meta("mergin.json"), "r") as file:
self._metadata = json.load(file)

self.is_old_metadata = "/" in self._metadata["name"]

def update_metadata(self, data: dict):
"""Writes project metadata and updates cached metadata."""
self._metadata = data
Expand Down
35 changes: 35 additions & 0 deletions mergin/test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2003,3 +2003,38 @@ def test_clean_diff_files(mc):
diff_files = glob.glob("*-diff-*", root_dir=os.path.split(mp.fpath_meta("inserted_1_A.gpkg"))[0])

assert diff_files == []


def test_project_metadata(mc):
test_project = "test_project_metadata"
project = API_USER + "/" + test_project
project_dir = os.path.join(TMP_DIR, test_project)

cleanup(mc, project, [project_dir])

# prepare local project
shutil.copytree(TEST_DATA_DIR, project_dir)

# copy metadata in old format
os.makedirs(os.path.join(project_dir, ".mergin"), exist_ok=True)
project_metadata = os.path.join(project_dir, ".mergin", "mergin.json")
metadata_file = os.path.join(project_dir, "old_metadata.json")
shutil.copyfile(metadata_file, project_metadata)

# verify we have correct metadata
mp = MerginProject(project_dir)
assert mp.project_full_name() == f"{API_USER}/{test_project}"
assert mp.project_name() == test_project
assert mp.workspace_name() == API_USER
assert mp.version() == "v0"

# copy metadata in new format
metadata_file = os.path.join(project_dir, "new_metadata.json")
shutil.copyfile(metadata_file, project_metadata)

# verify we have correct metadata
mp = MerginProject(project_dir)
assert mp.project_full_name() == f"{API_USER}/{test_project}"
assert mp.project_name() == test_project
assert mp.workspace_name() == API_USER
assert mp.version() == "v0"
43 changes: 43 additions & 0 deletions mergin/test/test_data/new_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"access": {
"owners": [
2
],
"ownersnames": [
"test_plugin"
],
"public": false,
"readers": [
2
],
"readersnames": [
"test_plugin"
],
"writers": [
2
],
"writersnames": [
"test_plugin"
]
},
"created": "2023-10-16T09:17:27Z",
"creator": 2,
"disk_usage": 0,
"files": [],
"id": "a6f9d38c-e30d-49f2-bfc5-76495afdbf27",
"name": "test_project_metadata",
"namespace": "test_plugin",
"permissions": {
"delete": true,
"update": true,
"upload": true
},
"removed_at": null,
"removed_by": null,
"role": "owner",
"tags": [],
"updated": "2023-10-16T09:17:27.345127",
"uploads": [],
"version": "v0",
"workspace_id": 18
}
6 changes: 6 additions & 0 deletions mergin/test/test_data/old_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "test_plugin/test_project_metadata",
"version": "v0",
"project_id": "effeca08-ef22-4fc1-b620-5261c6a081eb",
"files": []
}