8
8
{self} [--path=<path>] [-v -v...] <target> create <user>/<repo> [--add]
9
9
{self} [--path=<path>] [-v -v...] <target> delete <user>/<repo> [-f]
10
10
{self} [--path=<path>] [-v -v...] <target> open [<user>/<repo>]
11
+ {self} [--path=<path>] [-v -v...] <target> request [<user>/<repo>] (list|ls)
12
+ {self} [--path=<path>] [-v -v...] <target> request [<user>/<repo>] fetch <request>
13
+ {self} [--path=<path>] [-v -v...] <target> gist (list|ls) [<gist>]
14
+ {self} [--path=<path>] [-v -v...] <target> gist clone <gist>
15
+ {self} [--path=<path>] [-v -v...] <target> gist fetch <gist> [<gist_file>]
16
+ {self} [--path=<path>] [-v -v...] <target> gist create [--secret] <description> [<gist_path> <gist_path>...]
17
+ {self} [--path=<path>] [-v -v...] <target> gist delete <gist> [-f]
11
18
{self} --help
12
19
13
20
Tool for managing remote repository services.
18
25
fork Fork (and clone) the repository from the service
19
26
create Make this repository a new remote on the service
20
27
delete Delete the remote repository
28
+ gist Manages gist files
29
+ request Handles requests for merge
21
30
open Open the given or current repository in a browser
22
31
23
32
Options:
24
33
<user>/<repo> Repository to work with
25
- <branch> Branch to pull (when cloning) [default: master]
26
34
-p,--path=<path> Path to work on [default: .]
27
- -f,--force Do not ask for confirmation
28
- --clone Clone locally after fork
29
- --add Add to local repository after creation
30
35
-v,--verbose Makes it more chatty (repeat twice to see git commands)
31
36
-h,--help Shows this message
32
37
35
40
-t,--tracking <branch> Makes this remote tracking for the current branch
36
41
-a,--alone Does not add the remote to the 'all' remote
37
42
43
+ Options for fork and clone:
44
+ <branch> Branch to pull (when cloning) [default: master]
45
+ --clone Clone locally after fork
46
+
47
+ Options for create:
48
+ --add Add to local repository after creation
49
+
50
+ Options for delete:
51
+ -f,--force Do not ask for confirmation
52
+
53
+ Options for gist:
54
+ <gist> Identifier of the gist to fetch
55
+ <gist_file> Name of the file to fetch
56
+ <gist_path> Name of the file or directory to use for a new gist.
57
+ If path is a directory, all files directly within it
58
+ will be pushed. If a list of path is given, all files
59
+ from them will be pushed.
60
+ --secret Do not publicize gist when pushing
61
+
38
62
Configuration options:
39
63
alias Name to use for the git remote
40
64
url URL of the repository
41
- private-key Private key to use for connecting to the service
65
+ fqdn URL of the repository
42
66
type Name of the service to use (github, gitlab, bitbucket)
43
67
44
68
Configuration example:
45
69
46
70
[gitrepo "gitlab"]
47
- private-key = YourSecretKey
71
+ token = yourapitoken
48
72
alias = lab
49
73
50
74
[gitrepo "personal"]
51
75
type = gitlab
52
- private-key = YourSecretKey
53
- url = http:// custom.org
76
+ token = yourapitoken
77
+ fqdn = custom.org
54
78
55
79
{self} version {version}, Copyright ⓒ2016 Bernard `Guyzmo` Pratz
56
80
{self} comes with ABSOLUTELY NO WARRANTY; for more informations
83
107
from git import Repo , Git
84
108
from git .exc import InvalidGitRepositoryError , NoSuchPathError
85
109
110
+ def confirm (what , where ):
111
+ ans = input ('Are you sure you want to delete the '
112
+ '{} {} from the service?\n [yN]> ' .format (what , where ))
113
+ if 'y' in ans :
114
+ ans = input ('Are you really sure? there\' s no coming back!\n '
115
+ '[type \' burn!\' to proceed]> ' )
116
+ if 'burn!' != ans :
117
+ return False
118
+ else :
119
+ return False
120
+ return True
121
+
122
+
86
123
def main (args ):
87
124
try :
88
125
if args ['--verbose' ] >= 5 : # pragma: no cover
@@ -116,7 +153,7 @@ def main(args):
116
153
if 'GIT_WORK_TREE' in os .environ .keys () or 'GIT_DIR' in os .environ .keys (): #pragma: no cover
117
154
del os .environ ['GIT_WORK_TREE' ]
118
155
119
- if '/' in args ['<user>/<repo>' ]:
156
+ if args [ '<user>/<repo>' ] and '/' in args ['<user>/<repo>' ]:
120
157
if len (args ['<user>/<repo>' ].split ('/' )) > 2 :
121
158
raise ArgumentError ('Too many slashes.'
122
159
'Format of the parameter is <user>/<repo> or <repo>.' )
@@ -125,7 +162,7 @@ def main(args):
125
162
user = None
126
163
repo = args ['<user>/<repo>' ]
127
164
128
- if args ['create' ] or args ['add' ] or args ['delete' ] or args ['open' ]:
165
+ if args ['create' ] and not args [ 'gist' ] or args ['add' ] or args ['delete' ] and not args [ 'gist' ] or args ['open' ] or args [ 'request ' ]:
129
166
# Try to resolve existing repository path
130
167
try :
131
168
try :
@@ -156,14 +193,7 @@ def main(args):
156
193
157
194
elif args ['delete' ]:
158
195
if not args ['--force' ]: # pragma: no cover
159
- ans = input ('Are you sure you want to delete the repository '
160
- '{} from the server?\n [yN]> ' .format (args ['<user>/<repo>' ]))
161
- if 'y' in ans :
162
- ans = input ('Are you really sure? there\' s no coming back!\n '
163
- '[type \' burn!\' to proceed]> ' )
164
- if 'burn!' != ans :
165
- return 0
166
- else :
196
+ if not confirm ('repository' , args ['<user>/<repo>' ]):
167
197
return 0
168
198
169
199
if user :
@@ -175,6 +205,20 @@ def main(args):
175
205
service .name )
176
206
)
177
207
208
+ elif args ['request' ]:
209
+ if args ['list' ] or args ['ls' ]:
210
+ log .info ('List of open requests to merge:' )
211
+ log .info (" {}\t {}\t {}" .format ('id' , 'title' .ljust (60 ), 'URL' ))
212
+ for pr in service .request_list (user , repo ):
213
+ print ("{}\t {}\t {}" .format (pr [0 ].rjust (3 ), pr [1 ][:60 ].ljust (60 ), pr [2 ]))
214
+ elif args ['fetch' ] and args ['<request>' ]:
215
+ new_branch = service .request_fetch (user , repo , args ['<request>' ])
216
+ log .info ('Successfully fetched request id `{}` of `{}` into `{}`!' .format (
217
+ args ['<request>' ],
218
+ args ['<user>/<repo>' ],
219
+ new_branch )
220
+ )
221
+
178
222
elif args ['open' ]:
179
223
RepositoryService .get_service (None , args ['<target>' ]).open (user , repo )
180
224
@@ -196,7 +240,7 @@ def main(args):
196
240
raise FileExistsError ('Cannot clone repository, '
197
241
'a folder named {} already exists!' .format (repo ))
198
242
199
- elif args ['clone' ]:
243
+ elif args ['clone' ] and not args [ 'gist' ] :
200
244
repo_path = os .path .join (args ['--path' ], repo )
201
245
repository = Repo .init (repo_path )
202
246
service = RepositoryService .get_service (repository , args ['<target>' ])
@@ -207,6 +251,38 @@ def main(args):
207
251
)
208
252
return 0
209
253
254
+ elif args ['gist' ]:
255
+ service = RepositoryService .get_service (None , args ['<target>' ])
256
+ service .connect ()
257
+ if args ['list' ] or args ['ls' ]:
258
+ if args ['<gist>' ]:
259
+ log .info ("{:15}\t {:>7}\t {}" .format ('language' , 'size' , 'name' ))
260
+ for gist_file in service .gist_list (args ['<gist>' ]):
261
+ print ("{:15}\t {:7}\t {}" .format (* gist_file ))
262
+ else :
263
+ log .info ("{:56}\t {}" .format ('id' , 'title' .ljust (60 )))
264
+ for gist in service .gist_list ():
265
+ print ( "{:56}\t {}" .format (gist [0 ], gist [1 ]))
266
+ elif args ['fetch' ]:
267
+ # send gist to stdout, not using log.info on purpose here!
268
+ print (service .gist_fetch (args ['<gist>' ], args ['<gist_file>' ]))
269
+ elif args ['clone' ]:
270
+ repo_path = os .path .join (args ['--path' ], args ['<gist>' ].split ('/' )[- 1 ])
271
+ service .repository = Repo .init (repo_path )
272
+ service .gist_clone (args ['<gist>' ])
273
+ log .info ('Successfully cloned `{}` into `{}`!' .format ( args ['<gist>' ], repo_path ))
274
+ elif args ['create' ]:
275
+ url = service .gist_create (args ['<gist_path>' ], args ['<description>' ], args ['--secret' ])
276
+ log .info ('Successfully created gist `{}`!' .format (url ))
277
+ elif args ['delete' ]:
278
+ if not args ['--force' ]: # pragma: no cover
279
+ if not confirm ('gist' , args ['<gist>' ]):
280
+ return 0
281
+
282
+ service .gist_delete (args ['<gist>' ])
283
+ log .info ('Successfully deleted gist!' )
284
+ return 0
285
+
210
286
log .error ('Unknown action.' )
211
287
log .error ('Please consult help page (--help).' )
212
288
return 1
0 commit comments