Skip to content

Fix 180 #187

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 13 commits into from
Oct 13, 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
31 changes: 17 additions & 14 deletions mergin/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,12 @@ def create(ctx, project, public, from_dir):
mc = ctx.obj["client"]
if mc is None:
return
if "/" in project:
try:
namespace, project = project.split("/")
assert namespace, "No namespace given"
assert project, "No project name given"
except (ValueError, AssertionError) as e:
click.secho(f"Incorrect namespace/project format: {e}", fg="red")
return
else:
# namespace not specified, use current user namespace
namespace = mc.username()
try:
if from_dir is None:
mc.create_project(project, is_public=public, namespace=namespace)
mc.create_project(project, is_public=public)
click.echo("Created project " + project)
else:
mc.create_project_and_push(project, from_dir, is_public=public, namespace=namespace)
mc.create_project_and_push(project, from_dir, is_public=public)
click.echo("Created project " + project + " and pushed content from directory " + from_dir)
except ClientError as e:
click.secho("Error: " + str(e), fg="red")
Expand Down Expand Up @@ -555,7 +544,21 @@ def clone(ctx, source_project_path, cloned_project_name, cloned_project_namespac
if mc is None:
return
try:
mc.clone_project(source_project_path, cloned_project_name, cloned_project_namespace)
if cloned_project_namespace:
click.secho(
"The usage of `cloned_project_namespace` parameter in `mergin clone` is deprecated."
"Specify `cloned_project_name` as full name (<namespace>/<name>) instead.",
fg="yellow",
)
if cloned_project_namespace is None and "/" not in cloned_project_name:
click.secho(
"The use of only project name as `cloned_project_name` in `clone_project()` is deprecated."
"The `cloned_project_name` should be full name (<namespace>/<name>).",
fg="yellow",
)
if cloned_project_namespace and "/" not in cloned_project_name:
cloned_project_name = f"{cloned_project_namespace}/{cloned_project_name}"
mc.clone_project(source_project_path, cloned_project_name)
click.echo("Done")
except ClientError as e:
click.secho("Error: " + str(e), fg="red")
Expand Down
98 changes: 86 additions & 12 deletions mergin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import ssl
from enum import Enum, auto
import re
import warnings

from .common import ClientError, LoginError, InvalidProject
from .merginproject import MerginProject
Expand Down Expand Up @@ -434,44 +435,94 @@ def create_project(self, project_name, is_public=False, namespace=None):
Create new project repository in user namespace on Mergin Maps server.
Optionally initialized from given local directory.

:param project_name: Project name
:param project_name: Project's full name (<namespace>/<name>)
:type project_name: String

:param is_public: Flag for public/private project, defaults to False
:type is_public: Boolean

:param namespace: Optional namespace for a new project. If empty username is used.
:param namespace: Deprecated. project_name should be full project name. Optional namespace for a new project. If empty username is used.
:type namespace: String
"""
if not self._user_info:
raise Exception("Authentication required")

if namespace and "/" not in project_name:
warnings.warn(
"The usage of `namespace` parameter in `create_project()` is deprecated."
"Specify `project_name` as full name (<namespace>/<name>) instead.",
category=DeprecationWarning,
)

if "/" in project_name:
if namespace:
warnings.warn(
"Parameter `namespace` specified with full project name (<namespace>/<name>)."
"The parameter will be ignored."
)

namespace, project_name = project_name.split("/")

elif namespace is None:
warnings.warn(
"The use of only project name in `create_project()` is deprecated."
"The `project_name` should be full name (<namespace>/<name>).",
category=DeprecationWarning,
)

params = {"name": project_name, "public": is_public}
if namespace is None:
namespace = self.username()
try:
self.post("/v1/project/%s" % namespace, params, {"Content-Type": "application/json"})
self.post(f"/v1/project/{namespace}", params, {"Content-Type": "application/json"})
except Exception as e:
detail = f"Namespace: {namespace}, project name: {project_name}"
raise ClientError(str(e), detail)

def create_project_and_push(self, project_name, directory, is_public=False, namespace=None):
"""
Convenience method to create project and push the initial version right after that.

:param project_name: Project's full name (<namespace>/<name>)
:type project_name: String

:param namespace: Deprecated. project_name should be full project name. Optional namespace for a new project. If empty username is used.
:type namespace: String
"""
if os.path.exists(os.path.join(directory, ".mergin")):
raise ClientError("Directory is already assigned to a Mergin Maps project (contains .mergin sub-dir)")

if namespace is None:
if namespace and "/" not in project_name:
warnings.warn(
"The usage of `namespace` parameter in `create_project_and_push()` is deprecated."
"Specify `project_name` as full name (<namespace>/<name>) instead.",
category=DeprecationWarning,
)
project_name = f"{namespace}/{project_name}"

if "/" in project_name:
if namespace:
warnings.warn(
"Parameter `namespace` specified with full project name (<namespace>/<name>)."
"The parameter will be ignored."
)

elif namespace is None:
warnings.warn(
"The use of only project name in `create_project()` is deprecated."
"The `project_name` should be full name (<namespace>/<name>).",
category=DeprecationWarning,
)
namespace = self.username()
self.create_project(project_name, is_public, namespace)
project_name = f"{namespace}/{project_name}"

self.create_project(project_name, is_public)
if directory:
full_project_name = "{}/{}".format(namespace, project_name)
project_info = self.project_info(full_project_name)
project_info = self.project_info(project_name)
MerginProject.write_metadata(
directory,
{
"name": full_project_name,
"name": project_name,
"version": "v0",
"files": [],
"project_id": project_info["id"],
Expand Down Expand Up @@ -816,20 +867,43 @@ def clone_project(self, source_project_path, cloned_project_name, cloned_project
Clone project on server.
:param source_project_path: Project's full name (<namespace>/<name>)
:type source_project_path: String
:param cloned_project_name: Cloned project's name
:param cloned_project_name: Cloned project's full name (<namespace>/<name>)
:type cloned_project_name: String
:param cloned_project_namespace: Cloned project's namespace, username is used if not defined
:param cloned_project_namespace: Deprecated. cloned_project_name should be full project name. Cloned project's namespace, username is used if not defined
:type cloned_project_namespace: String

"""
path = "/v1/project/clone/%s" % source_project_path

if cloned_project_namespace and "/" not in cloned_project_name:
warnings.warn(
"The usage of `cloned_project_namespace` parameter in `clone_project()` is deprecated."
"Specify `cloned_project_name` as full name (<namespace>/<name>) instead.",
category=DeprecationWarning,
)

if "/" in cloned_project_name:
if cloned_project_namespace:
warnings.warn(
"Parameter `cloned_project_namespace` specified with full cloned project name (<namespace>/<name>)."
"The parameter will be ignored."
)

cloned_project_namespace, cloned_project_name = cloned_project_name.split("/")

elif cloned_project_namespace is None:
warnings.warn(
"The use of only project name as `cloned_project_name` in `clone_project()` is deprecated."
"The `cloned_project_name` should be full name (<namespace>/<name>).",
category=DeprecationWarning,
)

path = f"/v1/project/clone/{source_project_path}"
url = urllib.parse.urljoin(self.url, urllib.parse.quote(path))
json_headers = {"Content-Type": "application/json", "Accept": "application/json"}
data = {
"namespace": cloned_project_namespace if cloned_project_namespace else self.username(),
"project": cloned_project_name,
}

request = urllib.request.Request(url, data=json.dumps(data).encode(), headers=json_headers, method="POST")
self._do_request(request)

Expand Down
Loading