skilleter-thingy 0.0.75__py3-none-any.whl → 0.0.76__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/multigit.py +69 -10
- skilleter_thingy/thingy/git2.py +32 -0
- {skilleter_thingy-0.0.75.dist-info → skilleter_thingy-0.0.76.dist-info}/METADATA +1 -1
- {skilleter_thingy-0.0.75.dist-info → skilleter_thingy-0.0.76.dist-info}/RECORD +8 -8
- {skilleter_thingy-0.0.75.dist-info → skilleter_thingy-0.0.76.dist-info}/LICENSE +0 -0
- {skilleter_thingy-0.0.75.dist-info → skilleter_thingy-0.0.76.dist-info}/WHEEL +0 -0
- {skilleter_thingy-0.0.75.dist-info → skilleter_thingy-0.0.76.dist-info}/entry_points.txt +0 -0
- {skilleter_thingy-0.0.75.dist-info → skilleter_thingy-0.0.76.dist-info}/top_level.txt +0 -0
skilleter_thingy/multigit.py
CHANGED
|
@@ -25,6 +25,7 @@ import thingy.colour as colour
|
|
|
25
25
|
default branch = name
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
+
# TODO: [ ] If the config file isn't in the current directory then search up the directory tree for it but run in the current directory
|
|
28
29
|
# TODO: [ ] -j option to run in parallel?
|
|
29
30
|
# TODO: [ ] init function
|
|
30
31
|
# TODO: [/] Use the configuration file
|
|
@@ -37,6 +38,7 @@ import thingy.colour as colour
|
|
|
37
38
|
# TODO: [ ] Better error-handling - e.g. continue/abort option after failure in one repo
|
|
38
39
|
# TODO: [ ] Dry-run option
|
|
39
40
|
# TODO: [ ] Verbose option
|
|
41
|
+
# TODO: [ ] When specifying list of repos, if repo name doesn't contain '/' prefix it with '*'?
|
|
40
42
|
|
|
41
43
|
################################################################################
|
|
42
44
|
|
|
@@ -69,8 +71,13 @@ def show_progress(width, msg):
|
|
|
69
71
|
def find_git_repos(directory, wildcard):
|
|
70
72
|
"""Locate and return a list of '.git' directory parent directories in the
|
|
71
73
|
specified path.
|
|
74
|
+
|
|
72
75
|
If wildcard is not None then it is treated as a list of wildcards and
|
|
73
|
-
only repos matching at least one of the wildcards are returned.
|
|
76
|
+
only repos matching at least one of the wildcards are returned.
|
|
77
|
+
|
|
78
|
+
If the same repo matches multiple times it will only be returned once. """
|
|
79
|
+
|
|
80
|
+
repos = set()
|
|
74
81
|
|
|
75
82
|
for root, dirs, _ in os.walk(directory):
|
|
76
83
|
if '.git' in dirs:
|
|
@@ -80,10 +87,14 @@ def find_git_repos(directory, wildcard):
|
|
|
80
87
|
if wildcard:
|
|
81
88
|
for card in wildcard:
|
|
82
89
|
if fnmatch.fnmatch(root, card):
|
|
83
|
-
|
|
90
|
+
if root not in repos:
|
|
91
|
+
yield root
|
|
92
|
+
repos.add(root)
|
|
84
93
|
break
|
|
85
94
|
else:
|
|
86
|
-
|
|
95
|
+
if root not in repos:
|
|
96
|
+
yield root
|
|
97
|
+
repos.add(root)
|
|
87
98
|
|
|
88
99
|
################################################################################
|
|
89
100
|
|
|
@@ -261,7 +272,10 @@ def mg_checkout(args, config, console):
|
|
|
261
272
|
if the branch exists in the repo.
|
|
262
273
|
If the 'create' option is specified then branch is created"""
|
|
263
274
|
|
|
264
|
-
# TODO: Add --create handling
|
|
275
|
+
# TODO: [ ] Add --create handling
|
|
276
|
+
# TODO: [ ] Checkout remote branches
|
|
277
|
+
# TODO: [ ] only try checkout if branch exists
|
|
278
|
+
# TODO: [ ] option to fetch before checking out
|
|
265
279
|
|
|
266
280
|
for repo in find_git_repos(args.directory, args.repos):
|
|
267
281
|
if not args.quiet:
|
|
@@ -270,9 +284,9 @@ def mg_checkout(args, config, console):
|
|
|
270
284
|
branch = args.branch or config[repo]['default branch']
|
|
271
285
|
|
|
272
286
|
if git.branch(path=repo) != branch:
|
|
273
|
-
|
|
287
|
+
colour.write(f'Checking out [BLUE:{branch}] in [BOLD:{repo}]')
|
|
274
288
|
|
|
275
|
-
git.checkout(branch, path=repo)
|
|
289
|
+
git.checkout(branch, create=args.create, path=repo)
|
|
276
290
|
|
|
277
291
|
################################################################################
|
|
278
292
|
|
|
@@ -327,6 +341,36 @@ def mg_update(args, config, console):
|
|
|
327
341
|
|
|
328
342
|
################################################################################
|
|
329
343
|
|
|
344
|
+
def mg_clean(args, config, console):
|
|
345
|
+
"""Clean the repos"""
|
|
346
|
+
|
|
347
|
+
for repo in find_git_repos(args.directory, args.repos):
|
|
348
|
+
if not args.quiet:
|
|
349
|
+
show_progress(console.columns, repo)
|
|
350
|
+
|
|
351
|
+
result = git.clean(recurse=args.recurse, force=args.force, dry_run=args.dry_run,
|
|
352
|
+
quiet=args.quiet, exclude=args.exclude, ignore_rules=args.x,
|
|
353
|
+
remove_only_ignored=args.X, path=repo)
|
|
354
|
+
|
|
355
|
+
first_skip = True
|
|
356
|
+
|
|
357
|
+
if result:
|
|
358
|
+
colour.write(f'[BOLD:{repo}]')
|
|
359
|
+
|
|
360
|
+
for item in result:
|
|
361
|
+
skipping = item.startswith('Skipping repository ')
|
|
362
|
+
|
|
363
|
+
if skipping and not args.verbose:
|
|
364
|
+
if first_skip:
|
|
365
|
+
colour.write(f' Skipping sub-repositories')
|
|
366
|
+
first_skip = False
|
|
367
|
+
else:
|
|
368
|
+
colour.write(f' {item.strip()}')
|
|
369
|
+
|
|
370
|
+
colour.write()
|
|
371
|
+
|
|
372
|
+
################################################################################
|
|
373
|
+
|
|
330
374
|
def main():
|
|
331
375
|
"""Main function"""
|
|
332
376
|
|
|
@@ -339,6 +383,7 @@ def main():
|
|
|
339
383
|
'checkout': mg_checkout,
|
|
340
384
|
'commit': mg_commit,
|
|
341
385
|
'update': mg_update,
|
|
386
|
+
'clean': mg_clean,
|
|
342
387
|
}
|
|
343
388
|
|
|
344
389
|
# Parse args in the form COMMAND OPTIONS SUBCOMMAND SUBCOMMAND_OPTIONS PARAMETERS
|
|
@@ -351,7 +396,7 @@ def main():
|
|
|
351
396
|
parser.add_argument('--quiet', '-q', action='store_true', help='Minimal console output')
|
|
352
397
|
parser.add_argument('--config', '-c', action='store', default=DEFAULT_CONFIG_FILE, help=f'The configuration file (defaults to {DEFAULT_CONFIG_FILE})')
|
|
353
398
|
parser.add_argument('--directory', '--dir', action='store', default='.', help='The top-level directory of the multigit tree (defaults to the current directory)')
|
|
354
|
-
parser.add_argument('--repos', '-r', action='append', default=None, help='The
|
|
399
|
+
parser.add_argument('--repos', '-r', action='append', default=None, help='The repo names to work on (defaults to all repos and can contain shell wildcards and can be issued multiple times on the command line)')
|
|
355
400
|
|
|
356
401
|
subparsers = parser.add_subparsers(dest='command')
|
|
357
402
|
|
|
@@ -365,7 +410,7 @@ def main():
|
|
|
365
410
|
parser_push = subparsers.add_parser('push', help='Run git push in every repo where the current branch isn\'t the default and the most recent commit was by the current user')
|
|
366
411
|
|
|
367
412
|
parser_checkout = subparsers.add_parser('checkout', help='Checkout the specified branch')
|
|
368
|
-
parser_checkout.add_argument('--create', action='store_true', help='Create the specified branch and check it out')
|
|
413
|
+
parser_checkout.add_argument('--create', '-b', action='store_true', help='Create the specified branch and check it out')
|
|
369
414
|
parser_checkout.add_argument('branch', nargs='?', default=None, action='store', help='The branch name to check out (defaults to the default branch)')
|
|
370
415
|
|
|
371
416
|
parser_commit = subparsers.add_parser('commit', help='Commit changes')
|
|
@@ -373,6 +418,17 @@ def main():
|
|
|
373
418
|
|
|
374
419
|
parser_update = subparsers.add_parser('update', help='Pull the default branch and if the current branch isn\'t the default branch, rebase it onto the default branch')
|
|
375
420
|
|
|
421
|
+
parser_clean = subparsers.add_parser('clean', help='Remove untracked files from the working tree')
|
|
422
|
+
|
|
423
|
+
parser_clean.add_argument('--recurse', '-d', action='store_true', help='Recurse into subdirectories')
|
|
424
|
+
parser_clean.add_argument('--force', '-f', action='store_true', help='If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or directories unless given -f or -i')
|
|
425
|
+
#parser_clean.add_argument('--interactive', '-i', action='store_true', help='Show what would be done and clean files interactively.')
|
|
426
|
+
parser_clean.add_argument('--dry-run', '-n', action='store_true', help='Don’t actually remove anything, just show what would be done.')
|
|
427
|
+
#parser_clean.add_argument('--quiet', '-q', , action='store_true', help='Be quiet, only report errors, but not the files that are successfully removed.')
|
|
428
|
+
parser_clean.add_argument('--exclude', '-e', action='store', help='Use the given exclude pattern in addition to the standard ignore rules.')
|
|
429
|
+
parser_clean.add_argument('-x', action='store_true', help='Don’t use the standard ignore rules, but still use the ignore rules given with -e options from the command line.')
|
|
430
|
+
parser_clean.add_argument('-X', action='store_true', help='Remove only files ignored by Git. This may be useful to rebuild everything from scratch, but keep manually created files.')
|
|
431
|
+
|
|
376
432
|
# Parse the command line
|
|
377
433
|
|
|
378
434
|
args = parser.parse_args()
|
|
@@ -382,8 +438,6 @@ def main():
|
|
|
382
438
|
if not args.command:
|
|
383
439
|
error('No command specified')
|
|
384
440
|
|
|
385
|
-
# TODO: If the config file isn't in the current directory then search up the directory tree for it but run in the current directory
|
|
386
|
-
|
|
387
441
|
# If the configuration file exists, read it
|
|
388
442
|
|
|
389
443
|
config = configparser.ConfigParser()
|
|
@@ -418,9 +472,14 @@ def multigit():
|
|
|
418
472
|
main()
|
|
419
473
|
except KeyboardInterrupt:
|
|
420
474
|
sys.exit(1)
|
|
475
|
+
|
|
421
476
|
except BrokenPipeError:
|
|
422
477
|
sys.exit(2)
|
|
423
478
|
|
|
479
|
+
except git.GitError as exc:
|
|
480
|
+
print(exc)
|
|
481
|
+
sys.exit(3)
|
|
482
|
+
|
|
424
483
|
################################################################################
|
|
425
484
|
|
|
426
485
|
if __name__ == '__main__':
|
skilleter_thingy/thingy/git2.py
CHANGED
|
@@ -1239,6 +1239,38 @@ def log(branch1, branch2=None):
|
|
|
1239
1239
|
|
|
1240
1240
|
return git(cmd)
|
|
1241
1241
|
|
|
1242
|
+
################################################################################
|
|
1243
|
+
|
|
1244
|
+
def clean(recurse=False, force=False, dry_run=False, quiet=False,
|
|
1245
|
+
exclude=None, ignore_rules=False, remove_only_ignored=False, path=None):
|
|
1246
|
+
|
|
1247
|
+
""" Run git clean """
|
|
1248
|
+
|
|
1249
|
+
cmd = ['clean']
|
|
1250
|
+
|
|
1251
|
+
if recurse:
|
|
1252
|
+
cmd.append('-d')
|
|
1253
|
+
|
|
1254
|
+
if force:
|
|
1255
|
+
cmd.append('--force')
|
|
1256
|
+
|
|
1257
|
+
if dry_run:
|
|
1258
|
+
cmd.append('--dry-run')
|
|
1259
|
+
|
|
1260
|
+
if quiet:
|
|
1261
|
+
cmd.append('--quiet')
|
|
1262
|
+
|
|
1263
|
+
if exclude:
|
|
1264
|
+
cmd += ['--exclude', exclude]
|
|
1265
|
+
|
|
1266
|
+
if ignore_rules:
|
|
1267
|
+
cmd.append('-x')
|
|
1268
|
+
|
|
1269
|
+
if remove_only_ignored:
|
|
1270
|
+
cmd.append('-X')
|
|
1271
|
+
|
|
1272
|
+
return git(cmd, path=path)
|
|
1273
|
+
|
|
1242
1274
|
################################################################################
|
|
1243
1275
|
# Entry point
|
|
1244
1276
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: skilleter_thingy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.76
|
|
4
4
|
Summary: A collection of useful utilities, mainly aimed at making Git more friendly
|
|
5
5
|
Author-email: John Skilleter <john@skilleter.org.uk>
|
|
6
6
|
Project-URL: Home, https://skilleter.org.uk
|
|
@@ -25,7 +25,7 @@ skilleter_thingy/gl.py,sha256=9zbGpKxw6lX9RghLkdy-Q5sZlqtbB3uGFO04qTu1dH8,5954
|
|
|
25
25
|
skilleter_thingy/gphotosync.py,sha256=Vb2zYTEFp26BYdkG810SRg9afyfDqvq4CLHTk-MFf60,22388
|
|
26
26
|
skilleter_thingy/linecount.py,sha256=5voQtjJjDCVx4zjPwVRy620NpuLiwwFitzxjIsRGtxQ,4310
|
|
27
27
|
skilleter_thingy/moviemover.py,sha256=j_Xb9_jFdgpFBAXcF4tEqbnKH_FonlnUU39LiCK980k,4470
|
|
28
|
-
skilleter_thingy/multigit.py,sha256=
|
|
28
|
+
skilleter_thingy/multigit.py,sha256=TiPpPKO-xB0MUrV1Obv4UEZMi209vrcidFolDdFH8hM,18788
|
|
29
29
|
skilleter_thingy/photodupe.py,sha256=l0hbzSLb2Vk2ceteg-x9fHXCEE1uUuFo84hz5rsZUPA,4184
|
|
30
30
|
skilleter_thingy/phototidier.py,sha256=5gSjlINUxf3ZQl3NG0o7CsWwODvTbokIMIafLFvn8Hc,7818
|
|
31
31
|
skilleter_thingy/py_audit.py,sha256=xJm5k5qyeA6ii8mODa4dOkmP8L1drv94UHuxR54RsIM,4384
|
|
@@ -52,7 +52,7 @@ skilleter_thingy/thingy/dircolors.py,sha256=5NbXMsGWdABLvvZfB70VPmN6N5HyyihfpgoQ
|
|
|
52
52
|
skilleter_thingy/thingy/docker.py,sha256=9EFatudoVPfB1UbDEtzdJDB3o6ToHiNHv8-oLsUeqiQ,2449
|
|
53
53
|
skilleter_thingy/thingy/files.py,sha256=oW6E6WWwVFSUPdrZnKMx7P_w_hh3etjoN7RrqvYHCHc,4705
|
|
54
54
|
skilleter_thingy/thingy/git.py,sha256=qXWIduF4jbP5pKFYt_hW9Ex5iL9mSBBrcNKBkULhRTg,38834
|
|
55
|
-
skilleter_thingy/thingy/git2.py,sha256=
|
|
55
|
+
skilleter_thingy/thingy/git2.py,sha256=UEXeSyT5PlYGtdUAQDEZC7Sc7JmYdAlP6osa1tVmpO8,36620
|
|
56
56
|
skilleter_thingy/thingy/gitlab.py,sha256=uXAF918xnPk6qQyiwPQDbMZfqtJzhiRqDS7yEtJEIAg,6079
|
|
57
57
|
skilleter_thingy/thingy/path.py,sha256=8uM2Q9zFRWv_SaVOX49PeecQXttl7J6lsmBuRXWsXKY,4732
|
|
58
58
|
skilleter_thingy/thingy/popup.py,sha256=jW-nbpdeswqEMTli7OmBv1J8XQsvFoMI0J33O6dOeu8,2529
|
|
@@ -61,9 +61,9 @@ skilleter_thingy/thingy/run.py,sha256=6SNKWF01fSxzB10GMU9ajraXYZqAL1w0PXkqjJdr1U
|
|
|
61
61
|
skilleter_thingy/thingy/tfm_pane.py,sha256=oqy5zBzKwfbjbGqetbbhpKi4x5He7sl4qkmhUeqtdZc,19789
|
|
62
62
|
skilleter_thingy/thingy/tidy.py,sha256=71DCyj0VJrj52RmjQyj1eOiQJIfy5EIPHuThOrS6ZTA,5876
|
|
63
63
|
skilleter_thingy/thingy/venv_template.py,sha256=SsVNvSwojd8NnFeQaZPCRQYTNdwJRplpZpygbUEXRnY,1015
|
|
64
|
-
skilleter_thingy-0.0.
|
|
65
|
-
skilleter_thingy-0.0.
|
|
66
|
-
skilleter_thingy-0.0.
|
|
67
|
-
skilleter_thingy-0.0.
|
|
68
|
-
skilleter_thingy-0.0.
|
|
69
|
-
skilleter_thingy-0.0.
|
|
64
|
+
skilleter_thingy-0.0.76.dist-info/LICENSE,sha256=ljOS4DjXvqEo5VzGfdaRwgRZPbNScGBmfwyC8PChvmQ,32422
|
|
65
|
+
skilleter_thingy-0.0.76.dist-info/METADATA,sha256=88wOrTIgIDHyAdQssoVO1z_DCE0rWxNey0c8XnJEjq0,5313
|
|
66
|
+
skilleter_thingy-0.0.76.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
67
|
+
skilleter_thingy-0.0.76.dist-info/entry_points.txt,sha256=uW11ofmIbfPP_5B-pxb8YDkHbeZ_xeCoO6358R9wGVI,2146
|
|
68
|
+
skilleter_thingy-0.0.76.dist-info/top_level.txt,sha256=8-JhgToBBiWURunmvfpSxEvNkDHQQ7r25-aBXtZv61g,17
|
|
69
|
+
skilleter_thingy-0.0.76.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|