skilleter-thingy 0.0.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of skilleter-thingy might be problematic. Click here for more details.
- skilleter_thingy/__init__.py +0 -0
- skilleter_thingy/addpath.py +107 -0
- skilleter_thingy/aws.py +548 -0
- skilleter_thingy/borger.py +269 -0
- skilleter_thingy/colour.py +213 -0
- skilleter_thingy/console_colours.py +63 -0
- skilleter_thingy/dc_curses.py +278 -0
- skilleter_thingy/dc_defaults.py +221 -0
- skilleter_thingy/dc_util.py +50 -0
- skilleter_thingy/dircolors.py +308 -0
- skilleter_thingy/diskspacecheck.py +67 -0
- skilleter_thingy/docker.py +95 -0
- skilleter_thingy/docker_purge.py +113 -0
- skilleter_thingy/ffind.py +536 -0
- skilleter_thingy/files.py +142 -0
- skilleter_thingy/ggit.py +90 -0
- skilleter_thingy/ggrep.py +154 -0
- skilleter_thingy/git.py +1368 -0
- skilleter_thingy/git2.py +1307 -0
- skilleter_thingy/git_br.py +180 -0
- skilleter_thingy/git_ca.py +142 -0
- skilleter_thingy/git_cleanup.py +287 -0
- skilleter_thingy/git_co.py +220 -0
- skilleter_thingy/git_common.py +61 -0
- skilleter_thingy/git_hold.py +154 -0
- skilleter_thingy/git_mr.py +92 -0
- skilleter_thingy/git_parent.py +77 -0
- skilleter_thingy/git_review.py +1416 -0
- skilleter_thingy/git_update.py +385 -0
- skilleter_thingy/git_wt.py +96 -0
- skilleter_thingy/gitcmp_helper.py +322 -0
- skilleter_thingy/gitlab.py +193 -0
- skilleter_thingy/gitprompt.py +274 -0
- skilleter_thingy/gl.py +174 -0
- skilleter_thingy/gphotosync.py +610 -0
- skilleter_thingy/linecount.py +155 -0
- skilleter_thingy/logger.py +112 -0
- skilleter_thingy/moviemover.py +133 -0
- skilleter_thingy/path.py +156 -0
- skilleter_thingy/photodupe.py +110 -0
- skilleter_thingy/phototidier.py +248 -0
- skilleter_thingy/popup.py +87 -0
- skilleter_thingy/process.py +112 -0
- skilleter_thingy/py_audit.py +131 -0
- skilleter_thingy/readable.py +270 -0
- skilleter_thingy/remdir.py +126 -0
- skilleter_thingy/rmdupe.py +550 -0
- skilleter_thingy/rpylint.py +91 -0
- skilleter_thingy/run.py +334 -0
- skilleter_thingy/s3_sync.py +383 -0
- skilleter_thingy/splitpics.py +99 -0
- skilleter_thingy/strreplace.py +82 -0
- skilleter_thingy/sysmon.py +435 -0
- skilleter_thingy/tfm.py +920 -0
- skilleter_thingy/tfm_pane.py +595 -0
- skilleter_thingy/tfparse.py +101 -0
- skilleter_thingy/tidy.py +160 -0
- skilleter_thingy/trimpath.py +84 -0
- skilleter_thingy/window_rename.py +92 -0
- skilleter_thingy/xchmod.py +125 -0
- skilleter_thingy/yamlcheck.py +89 -0
- skilleter_thingy-0.0.22.dist-info/LICENSE +619 -0
- skilleter_thingy-0.0.22.dist-info/METADATA +22 -0
- skilleter_thingy-0.0.22.dist-info/RECORD +67 -0
- skilleter_thingy-0.0.22.dist-info/WHEEL +5 -0
- skilleter_thingy-0.0.22.dist-info/entry_points.txt +43 -0
- skilleter_thingy-0.0.22.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
""" Thingy gitprompt command
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2017 John Skilleter
|
|
6
|
+
|
|
7
|
+
Used to create the portion of the shell prompt that optionally shows
|
|
8
|
+
the current git repo name and branch and to output a colour code indicating
|
|
9
|
+
the status of the current working tree.
|
|
10
|
+
|
|
11
|
+
Normally used in the shell setup scripts (e.g. ~/.bashrc) as:
|
|
12
|
+
|
|
13
|
+
export PS1=$(gitprompt OPTIONS)
|
|
14
|
+
|
|
15
|
+
Command line options:
|
|
16
|
+
|
|
17
|
+
'--colour'
|
|
18
|
+
|
|
19
|
+
Output a background colour code indicating the status of the
|
|
20
|
+
current tree, rather than the repo name and branch.
|
|
21
|
+
|
|
22
|
+
Colours used are:
|
|
23
|
+
|
|
24
|
+
Green - Clean repo, no local changes
|
|
25
|
+
Cyan - Clean repo with untracked file(s)
|
|
26
|
+
Yellow - Uncommitted local changes (added, copied or renamed files)
|
|
27
|
+
Red - Local changes that have not been added (files modified or deleted)
|
|
28
|
+
Magenta - Unmerged files
|
|
29
|
+
|
|
30
|
+
Other options are set via the Git configuration:
|
|
31
|
+
|
|
32
|
+
prompt.prefix: 0 - No prefix
|
|
33
|
+
1 - Single letter indications of git status (untracked, modified, etc)
|
|
34
|
+
2 - One word indications (untracked, modified, etc)
|
|
35
|
+
|
|
36
|
+
TODO: Limit the total prompt length more 'intelligently', rather than just bits of it.
|
|
37
|
+
TODO: Indicate whether current directory is writeable and/or put current owner in prompt if no the current user
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
################################################################################
|
|
41
|
+
|
|
42
|
+
# Try and reduce the scope for an auto-repeating ^C to screw up the shell prompt
|
|
43
|
+
|
|
44
|
+
import signal
|
|
45
|
+
|
|
46
|
+
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
47
|
+
|
|
48
|
+
import os
|
|
49
|
+
import sys
|
|
50
|
+
import argparse
|
|
51
|
+
|
|
52
|
+
from skilleter_thingy import git
|
|
53
|
+
from skilleter_thingy import colour
|
|
54
|
+
|
|
55
|
+
################################################################################
|
|
56
|
+
# Constants
|
|
57
|
+
|
|
58
|
+
# Prefix text used when showing git status in the prompt - first entry is the
|
|
59
|
+
# abbreviated form and the second is the verbose.
|
|
60
|
+
|
|
61
|
+
STATUS_PREFIX = \
|
|
62
|
+
{
|
|
63
|
+
'untracked': ('u', 'untracked'),
|
|
64
|
+
'added': ('A', 'added'),
|
|
65
|
+
'modified': ('M', 'modified'),
|
|
66
|
+
'unmerged': ('U', 'unmerged'),
|
|
67
|
+
'deleted': ('D', 'deleted'),
|
|
68
|
+
'copied': ('C', 'copied'),
|
|
69
|
+
'renamed': ('R', 'renamed'),
|
|
70
|
+
'stash': ('S', 'stashed')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
MAX_BRANCH_NAME_LENGTH = int(os.environ.get('COLUMNS', 96)) / 3
|
|
74
|
+
|
|
75
|
+
################################################################################
|
|
76
|
+
|
|
77
|
+
def write_colour_prompt(gitstate: dict):
|
|
78
|
+
""" Output the colour for the prompt, according to the current state of the
|
|
79
|
+
working tree. """
|
|
80
|
+
|
|
81
|
+
colour.write('[NORMAL]', newline=False)
|
|
82
|
+
|
|
83
|
+
if gitstate['modified'] or gitstate['deleted']:
|
|
84
|
+
colour.write('[REVERSE][RED]', newline=False)
|
|
85
|
+
|
|
86
|
+
elif gitstate['added'] or gitstate['copied'] or gitstate['renamed']:
|
|
87
|
+
colour.write('[REVERSE][YELLOW]', newline=False)
|
|
88
|
+
|
|
89
|
+
elif gitstate['unmerged']:
|
|
90
|
+
colour.write('[REVERSE][MAGENTA]', newline=False)
|
|
91
|
+
|
|
92
|
+
elif gitstate['untracked']:
|
|
93
|
+
colour.write('[REVERSE][CYAN]', newline=False)
|
|
94
|
+
|
|
95
|
+
elif gitstate['merging'] or gitstate['bisecting'] or gitstate['rebasing']:
|
|
96
|
+
colour.write('[REVERSE][BLACK]', newline=False)
|
|
97
|
+
|
|
98
|
+
else:
|
|
99
|
+
colour.write('[REVERSE][GREEN]', newline=False)
|
|
100
|
+
|
|
101
|
+
################################################################################
|
|
102
|
+
|
|
103
|
+
def write_prompt_prefix(gitstate: dict):
|
|
104
|
+
""" Build a prompt prefix containing the type and number
|
|
105
|
+
of changes in the repo. """
|
|
106
|
+
|
|
107
|
+
prefix = []
|
|
108
|
+
|
|
109
|
+
# Get the status configuration from gitconfig and restrict it to the
|
|
110
|
+
# range 0..2
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
status_prefix = int(git.config_get('prompt', 'prefix', defaultvalue='0'))
|
|
114
|
+
except ValueError:
|
|
115
|
+
status_prefix = 0
|
|
116
|
+
else:
|
|
117
|
+
status_prefix = max(min(status_prefix, 2), 0)
|
|
118
|
+
|
|
119
|
+
# Only output the status information if the prefix is non-zero
|
|
120
|
+
|
|
121
|
+
if status_prefix > 0:
|
|
122
|
+
i = status_prefix - 1
|
|
123
|
+
|
|
124
|
+
stashed = len(git.stash())
|
|
125
|
+
|
|
126
|
+
if stashed:
|
|
127
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['stash'][i], stashed))
|
|
128
|
+
|
|
129
|
+
if gitstate['untracked']:
|
|
130
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['untracked'][i], gitstate['untracked']))
|
|
131
|
+
|
|
132
|
+
if gitstate['added']:
|
|
133
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['added'][i], gitstate['added']))
|
|
134
|
+
|
|
135
|
+
if gitstate['modified']:
|
|
136
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['modified'][i], gitstate['modified']))
|
|
137
|
+
|
|
138
|
+
if gitstate['unmerged']:
|
|
139
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['unmerged'][i], gitstate['unmerged']))
|
|
140
|
+
|
|
141
|
+
if gitstate['deleted']:
|
|
142
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['deleted'][i], gitstate['deleted']))
|
|
143
|
+
|
|
144
|
+
if gitstate['copied']:
|
|
145
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['copied'][i], gitstate['copied']))
|
|
146
|
+
|
|
147
|
+
if gitstate['renamed']:
|
|
148
|
+
prefix.append('%s:%d' % (STATUS_PREFIX['renamed'][i], gitstate['renamed']))
|
|
149
|
+
|
|
150
|
+
# Get the current branch, tag or commit
|
|
151
|
+
|
|
152
|
+
branch = git.branch() or git.tag() or git.current_commit(short=True)
|
|
153
|
+
|
|
154
|
+
# TODO: More intelligent branch name pruning - currently just trims it if longer than limit
|
|
155
|
+
# TODO: Keep branch name up to minimum characters long - use more components if still shorter
|
|
156
|
+
|
|
157
|
+
if len(branch) > MAX_BRANCH_NAME_LENGTH:
|
|
158
|
+
truncated_name = None
|
|
159
|
+
|
|
160
|
+
for sep in (' ', '-', '_', '/'):
|
|
161
|
+
shortname = sep.join(branch.split(sep)[0:2])
|
|
162
|
+
if (truncated_name and len(truncated_name) > len(shortname)) or not truncated_name:
|
|
163
|
+
truncated_name = shortname
|
|
164
|
+
|
|
165
|
+
if truncated_name:
|
|
166
|
+
branch = '%s...' % truncated_name
|
|
167
|
+
|
|
168
|
+
if gitstate['rebasing']:
|
|
169
|
+
prefix.append('(rebasing)')
|
|
170
|
+
elif gitstate['bisecting']:
|
|
171
|
+
prefix.append('(bisecting)')
|
|
172
|
+
elif gitstate['merging']:
|
|
173
|
+
prefix.append('(merging)')
|
|
174
|
+
|
|
175
|
+
if prefix:
|
|
176
|
+
sys.stdout.write(' {%s}' % ' '.join(prefix))
|
|
177
|
+
|
|
178
|
+
project = git.project(short=True)
|
|
179
|
+
|
|
180
|
+
if project:
|
|
181
|
+
sys.stdout.write(f' {project}: {branch} ')
|
|
182
|
+
else:
|
|
183
|
+
sys.stdout.write(f' {branch} ')
|
|
184
|
+
|
|
185
|
+
################################################################################
|
|
186
|
+
|
|
187
|
+
def git_status(colour_output: str, prompt_output: str):
|
|
188
|
+
""" Catalogue the current state of the working tree then call the function
|
|
189
|
+
to either output a suitable colour or the prompt text or both """
|
|
190
|
+
|
|
191
|
+
# Get the working tree, just return if there's an error
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
working_tree = git.working_tree()
|
|
195
|
+
except git.GitError:
|
|
196
|
+
return
|
|
197
|
+
|
|
198
|
+
# Return if we are not in a working tree
|
|
199
|
+
|
|
200
|
+
if not working_tree:
|
|
201
|
+
return
|
|
202
|
+
|
|
203
|
+
# gitstate contains counters for numbers of modified (etc.) elements in the tree and flags to indicate
|
|
204
|
+
# whether we're currently in a merge/rebase/bisect state.
|
|
205
|
+
|
|
206
|
+
gitstate = {'modified': 0, 'added': 0, 'untracked': 0, 'unmerged': 0, 'deleted': 0, 'renamed': 0, 'copied': 0}
|
|
207
|
+
|
|
208
|
+
# Set flags if we are currently merging/rebasing/bisecting and get the current status
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
gitstate['merging'] = git.merging()
|
|
212
|
+
gitstate['rebasing'] = git.rebasing()
|
|
213
|
+
gitstate['bisecting'] = git.bisecting()
|
|
214
|
+
|
|
215
|
+
status = git.status()
|
|
216
|
+
except git.GitError as exc:
|
|
217
|
+
# Major failure of gitness - report the error and quit
|
|
218
|
+
|
|
219
|
+
if colour_output:
|
|
220
|
+
colour.write('[WHITE][BRED]', newline=False)
|
|
221
|
+
else:
|
|
222
|
+
colour.write(' ERROR: %s ' % exc.msg.split('\n')[0], newline=False)
|
|
223
|
+
|
|
224
|
+
return
|
|
225
|
+
|
|
226
|
+
# Count the number of files in each state
|
|
227
|
+
|
|
228
|
+
for st in status:
|
|
229
|
+
gitstate['untracked'] += '?' in st[0]
|
|
230
|
+
gitstate['added'] += 'A' in st[0]
|
|
231
|
+
gitstate['modified'] += 'M' in st[0]
|
|
232
|
+
gitstate['unmerged'] += 'U' in st[0]
|
|
233
|
+
gitstate['deleted'] += 'D' in st[0]
|
|
234
|
+
gitstate['copied'] += 'C' in st[0]
|
|
235
|
+
gitstate['renamed'] += 'R' in st[0]
|
|
236
|
+
|
|
237
|
+
# Set the output colour or output the prompt prefix
|
|
238
|
+
|
|
239
|
+
if colour_output:
|
|
240
|
+
write_colour_prompt(gitstate)
|
|
241
|
+
|
|
242
|
+
if prompt_output or not colour_output:
|
|
243
|
+
write_prompt_prefix(gitstate)
|
|
244
|
+
|
|
245
|
+
################################################################################
|
|
246
|
+
|
|
247
|
+
def main():
|
|
248
|
+
""" Parse the command line and output colour or status """
|
|
249
|
+
|
|
250
|
+
parser = argparse.ArgumentParser(description='Report current branch and, optionally, git repo name to be embedded in shell prompt')
|
|
251
|
+
parser.add_argument('--colour', action='store_true', help='Output colour code indicating working tree status')
|
|
252
|
+
parser.add_argument('--prompt', action='store_true', help='Output the prompt (default if --colour not specified)')
|
|
253
|
+
|
|
254
|
+
args = parser.parse_args()
|
|
255
|
+
|
|
256
|
+
git_status(args.colour, args.prompt)
|
|
257
|
+
|
|
258
|
+
################################################################################
|
|
259
|
+
|
|
260
|
+
def gitprompt():
|
|
261
|
+
"""Entry point"""
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
main()
|
|
265
|
+
|
|
266
|
+
except KeyboardInterrupt:
|
|
267
|
+
sys.exit(1)
|
|
268
|
+
except BrokenPipeError:
|
|
269
|
+
sys.exit(2)
|
|
270
|
+
|
|
271
|
+
################################################################################
|
|
272
|
+
|
|
273
|
+
if __name__ == '__main__':
|
|
274
|
+
gitprompt()
|
skilleter_thingy/gl.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
""" Nearly MVP of a command to do things to GitLab
|
|
4
|
+
Currently just implements the 'mr-list' command which outputs a list
|
|
5
|
+
of merge requests from all projects in CSV format.
|
|
6
|
+
|
|
7
|
+
TODO: Lots and lots of things! """
|
|
8
|
+
|
|
9
|
+
################################################################################
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
from collections import defaultdict
|
|
15
|
+
|
|
16
|
+
from skilleter_thingy import colour
|
|
17
|
+
from skilleter_thingy import gitlab
|
|
18
|
+
|
|
19
|
+
################################################################################
|
|
20
|
+
|
|
21
|
+
def mr_list(args):
|
|
22
|
+
""" List merge requests """
|
|
23
|
+
|
|
24
|
+
gl = gitlab.GitLab(args.server)
|
|
25
|
+
|
|
26
|
+
# TODO: Could incorporate some/all filtering in the request rather than getting all MRs and filtering them
|
|
27
|
+
|
|
28
|
+
mrs = gl.merge_requests(scope='all')
|
|
29
|
+
|
|
30
|
+
# TODO: Output format other than CSV
|
|
31
|
+
# TODO: More filtering
|
|
32
|
+
|
|
33
|
+
if args.summary:
|
|
34
|
+
authors = defaultdict(int)
|
|
35
|
+
reviewers = defaultdict(int)
|
|
36
|
+
combos = defaultdict(int)
|
|
37
|
+
|
|
38
|
+
count = 0
|
|
39
|
+
for mr in mrs:
|
|
40
|
+
author = mr['author']['username']
|
|
41
|
+
authors[author] += 1
|
|
42
|
+
|
|
43
|
+
if mr['state'] == 'merged':
|
|
44
|
+
try:
|
|
45
|
+
reviewer = mr['merged_by']['username']
|
|
46
|
+
except TypeError:
|
|
47
|
+
reviewer = 'UNKNOWN'
|
|
48
|
+
|
|
49
|
+
reviewers[reviewer] += 1
|
|
50
|
+
combos[f"{author}|{reviewer}"] += 1
|
|
51
|
+
|
|
52
|
+
count += 1
|
|
53
|
+
if args.limit and count > args.limit:
|
|
54
|
+
break
|
|
55
|
+
|
|
56
|
+
print('Number of merge requests by author')
|
|
57
|
+
|
|
58
|
+
for value in sorted(set(authors.values()), reverse=True):
|
|
59
|
+
for person in authors:
|
|
60
|
+
if authors[person] == value:
|
|
61
|
+
print(f' {person:32}: {authors[person]}')
|
|
62
|
+
|
|
63
|
+
print()
|
|
64
|
+
print('Number of merge requests by reviewer')
|
|
65
|
+
|
|
66
|
+
for value in sorted(set(reviewers.values()), reverse=True):
|
|
67
|
+
for person in reviewers:
|
|
68
|
+
if reviewers[person] == value:
|
|
69
|
+
print(f' {person:32}: {reviewers[person]}')
|
|
70
|
+
|
|
71
|
+
print()
|
|
72
|
+
print('Author/Reviewer combinations for merged changes')
|
|
73
|
+
|
|
74
|
+
for value in sorted(set(combos.values()), reverse=True):
|
|
75
|
+
for combo in combos:
|
|
76
|
+
if combos[combo] == value:
|
|
77
|
+
author, reviewer = combo.split('|')
|
|
78
|
+
|
|
79
|
+
print(f' Written by {author}, reviewed by {reviewer}: {combos[combo]}')
|
|
80
|
+
|
|
81
|
+
else:
|
|
82
|
+
print('state,merge id,project id,author,approver,title,merge date')
|
|
83
|
+
|
|
84
|
+
for mr in mrs:
|
|
85
|
+
if args.author and mr['author']['username'] != args.author:
|
|
86
|
+
continue
|
|
87
|
+
|
|
88
|
+
if mr['state'] == 'merged':
|
|
89
|
+
try:
|
|
90
|
+
merged_by = mr['merged_by']['username']
|
|
91
|
+
except TypeError:
|
|
92
|
+
merged_by = 'NONE'
|
|
93
|
+
|
|
94
|
+
if args.approver and merged_by != args.approver:
|
|
95
|
+
continue
|
|
96
|
+
|
|
97
|
+
if not args.summary:
|
|
98
|
+
print('%s,%s,%s,%s,%s,%s,"%s"' % (mr['state'], mr['id'], mr['project_id'],
|
|
99
|
+
mr['author']['username'], merged_by, mr['title'], mr['merged_at']))
|
|
100
|
+
elif args.all and not args.summary:
|
|
101
|
+
print('%s,%s,%s,%s,,"%s",' % (mr['state'], mr['id'], mr['project_id'], mr['author']['username'], mr['title']))
|
|
102
|
+
|
|
103
|
+
count += 1
|
|
104
|
+
if args.limit and count > args.limit:
|
|
105
|
+
break
|
|
106
|
+
|
|
107
|
+
################################################################################
|
|
108
|
+
|
|
109
|
+
def main():
|
|
110
|
+
""" Entry point """
|
|
111
|
+
|
|
112
|
+
parser = argparse.ArgumentParser(description='Gitlab commands')
|
|
113
|
+
|
|
114
|
+
parser.add_argument('--dryrun', '--dry-run', '-D', action='store_true', help='Dry-run comands')
|
|
115
|
+
parser.add_argument('--debug', '-d', action='store_true', help='Debug')
|
|
116
|
+
parser.add_argument('--verbose', '-v', action='store_true', help='Verbosity to the maximum')
|
|
117
|
+
parser.add_argument('--server', '-s', default=None, help='The GitLab server')
|
|
118
|
+
parser.add_argument('--token', '-t', default=None, help='The GitLab access token')
|
|
119
|
+
|
|
120
|
+
subparsers = parser.add_subparsers(dest='command')
|
|
121
|
+
|
|
122
|
+
parser_mr_list = subparsers.add_parser('mr-list', help='List merge requests')
|
|
123
|
+
parser_mr_list.add_argument('--all', action='store_true', help='List un-merged merge requests')
|
|
124
|
+
parser_mr_list.add_argument('--author', action='store', help='List merge requests created by a specific user')
|
|
125
|
+
parser_mr_list.add_argument('--approver', action='store', help='List merge requests approved by a specific user')
|
|
126
|
+
parser_mr_list.add_argument('--summary', action='store_true', help='Produce a summary report')
|
|
127
|
+
parser_mr_list.add_argument('--limit', action='store', type=int, help='Output the first N merge requests')
|
|
128
|
+
|
|
129
|
+
# TODO: Other subcommands
|
|
130
|
+
|
|
131
|
+
# Parse the command line
|
|
132
|
+
|
|
133
|
+
args = parser.parse_args()
|
|
134
|
+
|
|
135
|
+
# Check the server/token configuration
|
|
136
|
+
|
|
137
|
+
if not args.server:
|
|
138
|
+
args.server = os.environ.get('GITLAB_SERVER', None)
|
|
139
|
+
|
|
140
|
+
if not args.server:
|
|
141
|
+
colour.error('The GitLab server must be specified on the command line or via the [BLUE:GITLAB_SERVER] environment variable')
|
|
142
|
+
|
|
143
|
+
if not args.token:
|
|
144
|
+
args.token = os.environ.get('GITLAB_TOKEN', None)
|
|
145
|
+
|
|
146
|
+
if not args.token:
|
|
147
|
+
colour.error('GitLab access token must be specified on the command line or via the [BLUE:GITLAB_TOKEN] environment variable')
|
|
148
|
+
|
|
149
|
+
# Invoke the subcommand
|
|
150
|
+
|
|
151
|
+
if args.command == 'mr-list':
|
|
152
|
+
mr_list(args)
|
|
153
|
+
|
|
154
|
+
elif not args.command:
|
|
155
|
+
colour.error('No command specified')
|
|
156
|
+
else:
|
|
157
|
+
colour.error(f'Invalid command: "{args.command}"')
|
|
158
|
+
|
|
159
|
+
################################################################################
|
|
160
|
+
|
|
161
|
+
def gl():
|
|
162
|
+
"""Entry point"""
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
main()
|
|
166
|
+
except KeyboardInterrupt:
|
|
167
|
+
sys.exit(1)
|
|
168
|
+
except BrokenPipeError:
|
|
169
|
+
sys.exit(2)
|
|
170
|
+
|
|
171
|
+
################################################################################
|
|
172
|
+
|
|
173
|
+
if __name__ == '__main__':
|
|
174
|
+
gl()
|