@@ -85,7 +85,7 @@ def pretty_summary(summary):
8585 )
8686
8787
88- def get_token (url , username , password , show_token = False ):
88+ def get_token (url , username , password , show_token = True ):
8989 """Get authorization token for given user and password."""
9090 mc = MerginClient (url )
9191 if not mc .is_server_compatible ():
@@ -97,24 +97,22 @@ def get_token(url, username, password, show_token=False):
9797 click .secho ("Unable to log in: " + str (e ), fg = "red" )
9898 return None
9999 if show_token :
100- click .secho (f'export MERGIN_AUTH="{ session ["token" ]} "' )
101- else :
102- click .secho (f"auth_token created (use --show_token option to see the token)." )
100+ click .secho (f'To set the MERGIN_AUTH variable run:\n export MERGIN_AUTH="{ session ["token" ]} "' )
103101 return session ["token" ]
104102
105103
106- def get_client (url = None , auth_token = None , username = None , password = None , show_token = False ):
104+ def get_client (url = None , auth_token = None , username = None , password = None ):
107105 """Return Mergin client."""
108106 if auth_token is not None :
109107 mc = MerginClient (url , auth_token = f"Bearer { auth_token } " )
110108 # Check if the token has expired or is just about to expire
111109 delta = mc ._auth_session ["expire" ] - datetime .now (timezone .utc )
112110 if delta .total_seconds () > 5 :
113- if show_token :
114- click .secho (f'export MERGIN_AUTH="{ auth_token } "' )
115111 return mc
116112 if username and password :
117- auth_token = get_token (url , username , password , show_token = show_token )
113+ auth_token = get_token (url , username , password )
114+ if auth_token is None :
115+ return None
118116 mc = MerginClient (url , auth_token = f"Bearer { auth_token } " )
119117 else :
120118 click .secho (
@@ -139,40 +137,41 @@ def _print_unhandled_exception():
139137@click .option (
140138 "--url" ,
141139 envvar = "MERGIN_URL" ,
142- default = "https://public.cloudmergin.com" ,
143- help = "Mergin server URL. Default is: https://public.cloudmergin.com " ,
140+ default = MerginClient . default_url () ,
141+ help = f "Mergin server URL. Default is: { MerginClient . default_url () } " ,
144142)
145- @click .option ("--auth_token " , envvar = "MERGIN_AUTH" , help = "Mergin authentication token string" )
143+ @click .option ("--auth-token " , envvar = "MERGIN_AUTH" , help = "Mergin authentication token string" )
146144@click .option ("--username" , envvar = "MERGIN_USERNAME" )
147145@click .option ("--password" , cls = OptionPasswordIfUser , prompt = True , hide_input = True , envvar = "MERGIN_PASSWORD" )
148- @click .option (
149- "--show_token" ,
150- is_flag = True ,
151- help = "Flag for echoing the authentication token. Useful for setting the MERGIN_AUTH environment variable." ,
152- )
153146@click .pass_context
154- def cli (ctx , url , auth_token , username , password , show_token ):
147+ def cli (ctx , url , auth_token , username , password ):
155148 """
156149 Command line interface for the Mergin client module.
157- For user authentication on server, username and password need to be given either as environment variables
158- (MERGIN_USERNAME, MERGIN_PASSWORD), or as options (--username, --password).
159- To set MERGIN_AUTH variable, run the command with --show_token option to see the token and how to set it manually.
150+ For user authentication on server there are two options:
151+ 1. authorization token environment variable (MERGIN_AUTH) is defined, or
152+ 2. username and password need to be given either as environment variables (MERGIN_USERNAME, MERGIN_PASSWORD),
153+ or as command options (--username, --password).
154+ Run `mergin --username <your_user> login` to see how to set the token variable manually.
160155 """
161- mc = get_client (url = url , auth_token = auth_token , username = username , password = password , show_token = show_token )
156+ mc = get_client (url = url , auth_token = auth_token , username = username , password = password )
162157 ctx .obj = {"client" : mc }
163158
164159
160+ @cli .command ()
161+ @click .pass_context
162+ def login (ctx ):
163+ """Login to the service and see how to set the token environment variable."""
164+ mc = ctx .obj ["client" ]
165+ if mc is not None :
166+ click .secho ("Login successful!" , fg = "green" )
167+
168+
165169@cli .command ()
166170@click .argument ("project" )
167171@click .option ("--public" , is_flag = True , default = False , help = "Public project, visible to everyone" )
168- @click .option ("--namespace" , help = "Namespace for the new project. Default is current Mergin user namespace." )
169172@click .pass_context
170- def create (ctx , project , public , namespace ):
171- """
172- Create a new project on Mergin server.
173- `project` can be a combination of namespace/project. Namespace can also be specified as an option, however if
174- namespace is specified as a part of `project` argument, the option is ignored.
175- """
173+ def create (ctx , project , public ):
174+ """Create a new project on Mergin server. `project` needs to be a combination of namespace/project."""
176175 mc = ctx .obj ["client" ]
177176 if mc is None :
178177 return
@@ -184,6 +183,9 @@ def create(ctx, project, public, namespace):
184183 except (ValueError , AssertionError ) as e :
185184 click .secho (f"Incorrect namespace/project format: { e } " , fg = "red" )
186185 return
186+ else :
187+ # namespace not specified, use current user namespace
188+ namespace = mc .username ()
187189 try :
188190 mc .create_project (project , is_public = public , namespace = namespace )
189191 click .echo ("Remote project created" )
@@ -404,24 +406,6 @@ def show_file_changeset(ctx, path, version):
404406 click .secho (json .dumps (info_dict , indent = 2 ))
405407
406408
407- @cli .command ()
408- @click .argument ("directory" , required = False )
409- def modtime (directory ):
410- """
411- Show files modification time info. For debug purposes only.
412- """
413- directory = os .path .abspath (directory or os .getcwd ())
414- strip_len = len (directory ) + 1
415- for root , dirs , files in os .walk (directory , topdown = True ):
416- for entry in dirs + files :
417- abs_path = os .path .abspath (os .path .join (root , entry ))
418- click .echo (abs_path [strip_len :])
419- # click.secho('atime %s' % datetime.fromtimestamp(os.path.getatime(abs_path)), fg="cyan")
420- click .secho ("mtime %s" % datetime .fromtimestamp (os .path .getmtime (abs_path )), fg = "cyan" )
421- # click.secho('ctime %s' % datetime.fromtimestamp(os.path.getctime(abs_path)), fg="cyan")
422- click .echo ()
423-
424-
425409@cli .command ()
426410@click .argument ("source_project_path" , required = True )
427411@click .argument ("cloned_project_name" , required = True )
@@ -447,8 +431,19 @@ def remove(ctx, project):
447431 mc = ctx .obj ["client" ]
448432 if mc is None :
449433 return
434+ if "/" in project :
435+ try :
436+ namespace , project = project .split ("/" )
437+ assert namespace , "No namespace given"
438+ assert project , "No project name given"
439+ except (ValueError , AssertionError ) as e :
440+ click .secho (f"Incorrect namespace/project format: { e } " , fg = "red" )
441+ return
442+ else :
443+ # namespace not specified, use current user namespace
444+ namespace = mc .username ()
450445 try :
451- mc .delete_project (project )
446+ mc .delete_project (f" { namespace } / { project } " )
452447 click .echo ("Remote project removed" )
453448 except Exception as e :
454449 _print_unhandled_exception ()
0 commit comments