skilleter-thingy 0.1.26__py3-none-any.whl → 0.1.28__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 +76 -35
- {skilleter_thingy-0.1.26.dist-info → skilleter_thingy-0.1.28.dist-info}/METADATA +4 -2
- {skilleter_thingy-0.1.26.dist-info → skilleter_thingy-0.1.28.dist-info}/RECORD +7 -7
- {skilleter_thingy-0.1.26.dist-info → skilleter_thingy-0.1.28.dist-info}/WHEEL +0 -0
- {skilleter_thingy-0.1.26.dist-info → skilleter_thingy-0.1.28.dist-info}/entry_points.txt +0 -0
- {skilleter_thingy-0.1.26.dist-info → skilleter_thingy-0.1.28.dist-info}/licenses/LICENSE +0 -0
- {skilleter_thingy-0.1.26.dist-info → skilleter_thingy-0.1.28.dist-info}/top_level.txt +0 -0
skilleter_thingy/multigit.py
CHANGED
|
@@ -28,6 +28,8 @@ import thingy.colour as colour
|
|
|
28
28
|
# DONE: command to categorise working trees then command line filter to only act on working trees in category (in addition to other filtering options) - +tag <TAG> command tags all selected working trees and updates the configuration, +untag <TAG> command to remove tags in the same way
|
|
29
29
|
# DONE: init function
|
|
30
30
|
# DONE Consistent colours in output
|
|
31
|
+
# DONE:+run command to do things other than git commands
|
|
32
|
+
# DONE: Command that takes partial working tree name and either returns full path or pops up window to autocomplete until single match found - returns list of paths you can pipe into fzf
|
|
31
33
|
#
|
|
32
34
|
# NOPE: Clone to have option to update - as discussed, should be part of init
|
|
33
35
|
# NOPE: Dry-run option - just pass the option to the Git command
|
|
@@ -37,14 +39,12 @@ import thingy.colour as colour
|
|
|
37
39
|
# NOPE: Use PathLib - Don't really see the need
|
|
38
40
|
# NOPE: When we have something with multiple matches display a menu for user to select the one that they one - make it a library routine so can be used, for instance, for branch selection - Use fzf
|
|
39
41
|
# NOPE: Use pygit2 directly - don't see the need
|
|
42
|
+
# NOPE: .init option '--update' to update the configuration file with new working trees and remove ones that are no longer there - init does the removal, and added the '+add' command instead
|
|
43
|
+
# NOPE: Ability to read default configuration options from ~/.config/thingy/multigit.rc - these are insert before argv[1] before argparse called - limited use for this
|
|
40
44
|
#
|
|
41
|
-
# TODO: 2 .init option '--update' to update the configuration file with new working trees and remove ones that are no longer there
|
|
42
|
-
# TODO: 2. +run command to do things other than git commands
|
|
43
45
|
# TODO: 2. If run in a subdirectory, only process working trees in that tree (or have an option to do so, or an option _not_ to do so; --all)
|
|
44
46
|
# TODO: 2. select_git_repos() and +dir should use consist way of selecting repos if possible
|
|
45
47
|
# TODO: 3 .init option '--set-default' to update the default branch to the current one for specified working trees
|
|
46
|
-
# TODO: 3. Ability to read default configuration options from ~/.config/thingy/multigit.rc - these are insert before argv[1] before argparse called
|
|
47
|
-
# TODO: 3. Command that takes partial working tree name and either returns full path or pops up window to autocomplete until single match found
|
|
48
48
|
# TODO: 3. Verbose option
|
|
49
49
|
# TODO: 3. When filtering by tag or by repo name, if name starts with '!' only match if tag isn't present or repo name doesn't match (and don't allow '!' at start of tag otherwise)
|
|
50
50
|
# TODO: 3. (alternative to above) A '--not' option that inverts all the matching criteria, so '--not --branched --modified' selects all unmodified repos which aren't branched
|
|
@@ -67,7 +67,7 @@ DEFAULT_BRANCH = 'DEFAULT'
|
|
|
67
67
|
# commands are parameters so we have to manually create the help and parse the command line
|
|
68
68
|
|
|
69
69
|
HELP_INFO = """usage: multigit [--help|-h] [--verbose|-v] [--quiet|-q] [--config|-c CONFIG] [--repos|-r REPOS] [--modified|-m] [--branched|-b] [--sub|-s] [--tag|-t TAGS] [--continue|-o] [--path|-C PATH]
|
|
70
|
-
{+clone, +init, +config, +dir, +list, +run, GIT_COMMAND} ...
|
|
70
|
+
{+clone, +init, +config, +dir, +list, +run, +add, GIT_COMMAND} ...
|
|
71
71
|
|
|
72
72
|
Run git commands in multiple Git repos. DISCLAIMER: This is beta-quality software, with missing features and liable to fail with a stack trace, but shouldn't eat your data
|
|
73
73
|
|
|
@@ -87,7 +87,7 @@ options:
|
|
|
87
87
|
--path, -C PATH Run as if the command was started in PATH instead of the current working directory
|
|
88
88
|
|
|
89
89
|
Sub-commands:
|
|
90
|
-
{+clone, +init, +dir, +config, +list, +run, GIT_COMMAND}
|
|
90
|
+
{+clone, +init, +dir, +config, +list, +run, +add, GIT_COMMAND}
|
|
91
91
|
+clone REPO {BRANCH} Clone a repo containing a multigit configuration file, then clone all the child repos and check out the default branch in each
|
|
92
92
|
+init Build or update the configuration file using the current branch in each repo as the default branch
|
|
93
93
|
+config Return the name and location of the configuration file
|
|
@@ -96,6 +96,7 @@ Sub-commands:
|
|
|
96
96
|
+tag TAG Apply a configuration tag to repos filtered by the command line options (list configuration tags if no parameter specified)
|
|
97
97
|
+untag TAG Remove a configuration tag to repos filtered by the command line options
|
|
98
98
|
+run COMMAND Run the specified command in repos filtered by the command line options
|
|
99
|
+
+add REPO DIR Clone REPO into the DIR directory and add it to the multigit configuration
|
|
99
100
|
GIT_COMMAND Any git command, including options and parameters - this is then run in all specified working trees
|
|
100
101
|
|
|
101
102
|
"""
|
|
@@ -310,9 +311,37 @@ def branch_name(name, default_branch):
|
|
|
310
311
|
|
|
311
312
|
################################################################################
|
|
312
313
|
|
|
314
|
+
def add_new_repo(args, config, repo):
|
|
315
|
+
"""Add a new configuration entry containing the default branch, remote origin
|
|
316
|
+
(if there is one) and name"""
|
|
317
|
+
|
|
318
|
+
abs_repo_path = absolute_repo_path(args, repo)
|
|
319
|
+
|
|
320
|
+
config[repo] = {}
|
|
321
|
+
|
|
322
|
+
default_branch = git.branch(path=abs_repo_path)
|
|
323
|
+
|
|
324
|
+
if not default_branch:
|
|
325
|
+
colour.error(f'Unable to determine default branch in [BLUE:{repo}]', prefix=True)
|
|
326
|
+
|
|
327
|
+
config[repo]['default branch'] = default_branch
|
|
328
|
+
|
|
329
|
+
remote = git.remotes(path=abs_repo_path)
|
|
330
|
+
|
|
331
|
+
if 'origin' in remote:
|
|
332
|
+
config[repo]['origin'] = remote['origin']
|
|
333
|
+
config[repo]['repo name'] = os.path.basename(remote['origin']).removesuffix('.git')
|
|
334
|
+
else:
|
|
335
|
+
config[repo]['repo name'] = os.path.basename(repo)
|
|
336
|
+
|
|
337
|
+
if not args.quiet:
|
|
338
|
+
colour.write(f'Added [BLUE:{repo}] with default branch [BLUE:{default_branch}]')
|
|
339
|
+
|
|
340
|
+
################################################################################
|
|
341
|
+
|
|
313
342
|
def mg_clone(args, config, console):
|
|
314
343
|
"""Clone a repo, optionally check out a branch and attempt to read the
|
|
315
|
-
configuration file and clone all the repos listed therein, checkouting
|
|
344
|
+
multigit configuration file and clone all the repos listed therein, checkouting
|
|
316
345
|
the default branch in each one"""
|
|
317
346
|
|
|
318
347
|
_ = console
|
|
@@ -401,30 +430,7 @@ def mg_init(args, config, console):
|
|
|
401
430
|
repo_list.append(repo)
|
|
402
431
|
|
|
403
432
|
if repo not in config:
|
|
404
|
-
|
|
405
|
-
# (if there is one) and name
|
|
406
|
-
|
|
407
|
-
abs_repo_path = absolute_repo_path(args, repo)
|
|
408
|
-
|
|
409
|
-
config[repo] = {}
|
|
410
|
-
|
|
411
|
-
default_branch = git.branch(path=abs_repo_path)
|
|
412
|
-
|
|
413
|
-
if not default_branch:
|
|
414
|
-
colour.error(f'Unable to determine default branch in [BLUE:{repo}]', prefix=True)
|
|
415
|
-
|
|
416
|
-
config[repo]['default branch'] = default_branch
|
|
417
|
-
|
|
418
|
-
remote = git.remotes(path=abs_repo_path)
|
|
419
|
-
|
|
420
|
-
if 'origin' in remote:
|
|
421
|
-
config[repo]['origin'] = remote['origin']
|
|
422
|
-
config[repo]['repo name'] = os.path.basename(remote['origin']).removesuffix('.git')
|
|
423
|
-
else:
|
|
424
|
-
config[repo]['repo name'] = os.path.basename(repo)
|
|
425
|
-
|
|
426
|
-
if not args.quiet:
|
|
427
|
-
colour.write(f'Added [BLUE:{repo}] with default branch [BLUE:{default_branch}]')
|
|
433
|
+
add_new_repo(args, config, repo)
|
|
428
434
|
|
|
429
435
|
if not args.quiet:
|
|
430
436
|
colour.write(cleareol=True)
|
|
@@ -447,6 +453,39 @@ def mg_init(args, config, console):
|
|
|
447
453
|
|
|
448
454
|
################################################################################
|
|
449
455
|
|
|
456
|
+
def mg_add(args, config, console):
|
|
457
|
+
"""Add a new repo - takes 2 parameters; the repo to clone and the directory
|
|
458
|
+
to clone it into. If successful, adds the repo to the configuration"""
|
|
459
|
+
|
|
460
|
+
_ = console
|
|
461
|
+
_ = config
|
|
462
|
+
|
|
463
|
+
verbose(args, f'add: Parameters: {", ".join(args.parameters)}')
|
|
464
|
+
|
|
465
|
+
if len(args.parameters) != 2:
|
|
466
|
+
colour.error('The "[BOLD:+add]" command takes two parameters; the repo to clone the location to clone it into', prefix=True)
|
|
467
|
+
|
|
468
|
+
if args.modified or args.branched or args.tag or args.subdirectories:
|
|
469
|
+
colour.error('The "[BOLD:--tag]", "[BOLD:--modified]" "[BOLD:--sub]", and "[BOLD:--branched]" options cannot be used with the "[BOLD:+add]" subcommand', prefix=True)
|
|
470
|
+
|
|
471
|
+
repo = args.parameters[0]
|
|
472
|
+
location = args.parameters[1]
|
|
473
|
+
|
|
474
|
+
if os.path.exists(location):
|
|
475
|
+
colour.error(f'"[BLUE:{location}]" already exists', prefix=True)
|
|
476
|
+
|
|
477
|
+
git.clone(repo, path=location)
|
|
478
|
+
|
|
479
|
+
# Add to the configuration
|
|
480
|
+
|
|
481
|
+
add_new_repo(args, config, location)
|
|
482
|
+
|
|
483
|
+
# The configuration file needs to be updated
|
|
484
|
+
|
|
485
|
+
args.config_modified = True
|
|
486
|
+
|
|
487
|
+
################################################################################
|
|
488
|
+
|
|
450
489
|
def mg_dir(args, config, console):
|
|
451
490
|
"""Return the location of a working tree, given the name, or the root directory
|
|
452
491
|
of the tree if not
|
|
@@ -592,10 +631,10 @@ def mg_run(args, config, console):
|
|
|
592
631
|
repo_path = absolute_repo_path(args, repo.name)
|
|
593
632
|
|
|
594
633
|
try:
|
|
595
|
-
status = subprocess.run(args.parameters, cwd=repo_path)
|
|
634
|
+
status = subprocess.run(args.parameters, cwd=repo_path, check=False)
|
|
596
635
|
except FileNotFoundError:
|
|
597
636
|
err_msg = f'"[BLUE:{args.parameters[0]}]" - Command not found'
|
|
598
|
-
if args.error_continue:
|
|
637
|
+
if args.error_continue:
|
|
599
638
|
colour.write(f'[RED:WARNING]: {err_msg}')
|
|
600
639
|
else:
|
|
601
640
|
colour.error(f'[RED:ERROR]: {err_msg}')
|
|
@@ -619,8 +658,7 @@ def run_git_command(args, config, console):
|
|
|
619
658
|
for cmd in args.parameters:
|
|
620
659
|
repo_command.append(branch_name(cmd, repo['default branch']))
|
|
621
660
|
|
|
622
|
-
|
|
623
|
-
colour.write(f'\n[BLUE:{os.path.relpath(repo.name)}]\n')
|
|
661
|
+
colour.write(f'\n[BLUE:{os.path.relpath(repo.name)}]\n')
|
|
624
662
|
|
|
625
663
|
# Run the command in the working tree
|
|
626
664
|
|
|
@@ -766,6 +804,7 @@ COMMANDS = {
|
|
|
766
804
|
'untag': mg_untag,
|
|
767
805
|
'list': mg_list,
|
|
768
806
|
'run': mg_run,
|
|
807
|
+
'add': mg_add,
|
|
769
808
|
}
|
|
770
809
|
|
|
771
810
|
def main():
|
|
@@ -848,6 +887,8 @@ def multigit():
|
|
|
848
887
|
|
|
849
888
|
except git.GitError as exc:
|
|
850
889
|
sys.stderr.write(exc.msg)
|
|
890
|
+
sys.stderr.write('\n')
|
|
891
|
+
|
|
851
892
|
sys.exit(exc.status)
|
|
852
893
|
|
|
853
894
|
################################################################################
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: skilleter_thingy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.28
|
|
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
|
|
@@ -104,7 +104,7 @@ Multigit tags are stored in the configuration file, not within the working tree
|
|
|
104
104
|
|
|
105
105
|
Multigit supports a small list of subcommands, each of which are prefixed with a `+` to distinguish them from Git commands:
|
|
106
106
|
|
|
107
|
-
`+clone
|
|
107
|
+
`+clone REPO <BRANCH>` - Clone REPO (which should contain a multigit configuration file), checking out BRANCH, if specified, then clone all the repos specified in the configuration, checking out the default branch in each one.
|
|
108
108
|
|
|
109
109
|
`+init` - Create or update the configuration file
|
|
110
110
|
|
|
@@ -120,6 +120,8 @@ Multigit supports a small list of subcommands, each of which are prefixed with a
|
|
|
120
120
|
|
|
121
121
|
`+run COMMAND` - Run the specified command in each of the specified working trees
|
|
122
122
|
|
|
123
|
+
`+add REPO DIR` - Clone REPO into the DIR directory and, if successful, add it to the multigit configuration
|
|
124
|
+
|
|
123
125
|
Any command *not* prefixed with `+` is run in each of the working trees (filtered by the various multigit options) as a git command.
|
|
124
126
|
|
|
125
127
|
For example; `multigit -m commit -ab` would run `git commit -a` in each of the working trees that is branched and contains modified files.
|
|
@@ -25,7 +25,7 @@ skilleter_thingy/gl.py,sha256=9zbGpKxw6lX9RghLkdy-Q5sZlqtbB3uGFO04qTu1dH8,5954
|
|
|
25
25
|
skilleter_thingy/linecount.py,sha256=ehTN6VD76i4U5k6dXuYoiqSRHI67_BP-bziklNAJSKY,4309
|
|
26
26
|
skilleter_thingy/localphotosync.py,sha256=WF0TcCvLfl7cVOLzYYQK_t2WebLfQ-5FM6UB3r7Fpvw,5952
|
|
27
27
|
skilleter_thingy/moviemover.py,sha256=QzUAWQzQ1AWWREIhl-VMaLo2h8MMhOekBnao5jGWV1s,4470
|
|
28
|
-
skilleter_thingy/multigit.py,sha256=
|
|
28
|
+
skilleter_thingy/multigit.py,sha256=0OCg45ma70YWnsXGonevc2v5PQHEaW3eshKkI-eUiWQ,34512
|
|
29
29
|
skilleter_thingy/photodupe.py,sha256=2hw4EhDKH37_BgdXKkPm9GrftfIORmubQi38Yn0b4Mg,4084
|
|
30
30
|
skilleter_thingy/phototidier.py,sha256=BOu-cKHMivDlBqlRqv7sL3J6Ix1K2dxWWNcderldyZo,7818
|
|
31
31
|
skilleter_thingy/py_audit.py,sha256=4CAdqBAIIVcpTCn_7dGm56bdfGpUtUJofqTGZomClkY,4417
|
|
@@ -61,9 +61,9 @@ skilleter_thingy/thingy/run.py,sha256=6SNKWF01fSxzB10GMU9ajraXYZqAL1w0PXkqjJdr1U
|
|
|
61
61
|
skilleter_thingy/thingy/tfm_pane.py,sha256=XTTpSm71CyQyGmlVLuCthioOwech0jhUiFUXb-chS_Q,19792
|
|
62
62
|
skilleter_thingy/thingy/tidy.py,sha256=AQ2RawsZJg6WHrgayi_ZptFL9occ7suSdCHbU3P-cys,5971
|
|
63
63
|
skilleter_thingy/thingy/venv_template.py,sha256=SsVNvSwojd8NnFeQaZPCRQYTNdwJRplpZpygbUEXRnY,1015
|
|
64
|
-
skilleter_thingy-0.1.
|
|
65
|
-
skilleter_thingy-0.1.
|
|
66
|
-
skilleter_thingy-0.1.
|
|
67
|
-
skilleter_thingy-0.1.
|
|
68
|
-
skilleter_thingy-0.1.
|
|
69
|
-
skilleter_thingy-0.1.
|
|
64
|
+
skilleter_thingy-0.1.28.dist-info/licenses/LICENSE,sha256=ljOS4DjXvqEo5VzGfdaRwgRZPbNScGBmfwyC8PChvmQ,32422
|
|
65
|
+
skilleter_thingy-0.1.28.dist-info/METADATA,sha256=RjIkDjog59L5uWr-RaSGqVhsDFdF1Bg2XA--iSmG068,30430
|
|
66
|
+
skilleter_thingy-0.1.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
67
|
+
skilleter_thingy-0.1.28.dist-info/entry_points.txt,sha256=mklrWFvNKw9Hyem9RG3x0PoVYjlx2fDnJ3xWMTMOmfs,2258
|
|
68
|
+
skilleter_thingy-0.1.28.dist-info/top_level.txt,sha256=8-JhgToBBiWURunmvfpSxEvNkDHQQ7r25-aBXtZv61g,17
|
|
69
|
+
skilleter_thingy-0.1.28.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|