skilleter-thingy 0.1.25__tar.gz → 0.1.27__tar.gz

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.

Files changed (74) hide show
  1. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/PKG-INFO +6 -2
  2. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/README.md +5 -1
  3. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/pyproject.toml +1 -1
  4. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/multigit.py +114 -35
  5. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy.egg-info/PKG-INFO +6 -2
  6. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/LICENSE +0 -0
  7. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/setup.cfg +0 -0
  8. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/__init__.py +0 -0
  9. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/addpath.py +0 -0
  10. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/borger.py +0 -0
  11. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/console_colours.py +0 -0
  12. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/diskspacecheck.py +0 -0
  13. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/docker_purge.py +0 -0
  14. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/ffind.py +0 -0
  15. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/ggit.py +0 -0
  16. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/ggrep.py +0 -0
  17. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_br.py +0 -0
  18. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_ca.py +0 -0
  19. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_cleanup.py +0 -0
  20. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_co.py +0 -0
  21. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_common.py +0 -0
  22. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_hold.py +0 -0
  23. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_mr.py +0 -0
  24. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_parent.py +0 -0
  25. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_retag.py +0 -0
  26. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_review.py +0 -0
  27. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_update.py +0 -0
  28. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/git_wt.py +0 -0
  29. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/gitcmp_helper.py +0 -0
  30. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/gitprompt.py +0 -0
  31. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/gl.py +0 -0
  32. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/linecount.py +0 -0
  33. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/localphotosync.py +0 -0
  34. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/moviemover.py +0 -0
  35. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/photodupe.py +0 -0
  36. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/phototidier.py +0 -0
  37. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/py_audit.py +0 -0
  38. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/readable.py +0 -0
  39. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/remdir.py +0 -0
  40. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/rmdupe.py +0 -0
  41. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/rpylint.py +0 -0
  42. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/splitpics.py +0 -0
  43. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/strreplace.py +0 -0
  44. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/sysmon.py +0 -0
  45. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/tfm.py +0 -0
  46. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/tfparse.py +0 -0
  47. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/__init__.py +0 -0
  48. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/colour.py +0 -0
  49. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/dc_curses.py +0 -0
  50. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/dc_defaults.py +0 -0
  51. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/dc_util.py +0 -0
  52. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/dircolors.py +0 -0
  53. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/docker.py +0 -0
  54. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/files.py +0 -0
  55. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/git.py +0 -0
  56. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/git2.py +0 -0
  57. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/gitlab.py +0 -0
  58. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/path.py +0 -0
  59. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/popup.py +0 -0
  60. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/process.py +0 -0
  61. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/run.py +0 -0
  62. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/tfm_pane.py +0 -0
  63. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/tidy.py +0 -0
  64. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/thingy/venv_template.py +0 -0
  65. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/trimpath.py +0 -0
  66. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/venv_create.py +0 -0
  67. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/window_rename.py +0 -0
  68. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/xchmod.py +0 -0
  69. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy/yamlcheck.py +0 -0
  70. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy.egg-info/SOURCES.txt +0 -0
  71. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy.egg-info/dependency_links.txt +0 -0
  72. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy.egg-info/entry_points.txt +0 -0
  73. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy.egg-info/requires.txt +0 -0
  74. {skilleter_thingy-0.1.25 → skilleter_thingy-0.1.27}/skilleter_thingy.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skilleter_thingy
3
- Version: 0.1.25
3
+ Version: 0.1.27
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` - Clone a repo containing a multigit configuration file then clone all the repos specified in the configuration, checking out the default branch in each one.
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
 
@@ -118,6 +118,10 @@ Multigit supports a small list of subcommands, each of which are prefixed with a
118
118
 
119
119
  `+untag TAG` - Remove the tag from the specified working trees (do nothing if the tag is not applied in the first place).
120
120
 
121
+ `+run COMMAND` - Run the specified command in each of the specified working trees
122
+
123
+ `+add REPO DIR` - Clone REPO into the DIR directory and, if successful, add it to the multigit configuration
124
+
121
125
  Any command *not* prefixed with `+` is run in each of the working trees (filtered by the various multigit options) as a git command.
122
126
 
123
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.
@@ -81,7 +81,7 @@ Multigit tags are stored in the configuration file, not within the working tree
81
81
 
82
82
  Multigit supports a small list of subcommands, each of which are prefixed with a `+` to distinguish them from Git commands:
83
83
 
84
- `+clone` - Clone a repo containing a multigit configuration file then clone all the repos specified in the configuration, checking out the default branch in each one.
84
+ `+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.
85
85
 
86
86
  `+init` - Create or update the configuration file
87
87
 
@@ -95,6 +95,10 @@ Multigit supports a small list of subcommands, each of which are prefixed with a
95
95
 
96
96
  `+untag TAG` - Remove the tag from the specified working trees (do nothing if the tag is not applied in the first place).
97
97
 
98
+ `+run COMMAND` - Run the specified command in each of the specified working trees
99
+
100
+ `+add REPO DIR` - Clone REPO into the DIR directory and, if successful, add it to the multigit configuration
101
+
98
102
  Any command *not* prefixed with `+` is run in each of the working trees (filtered by the various multigit options) as a git command.
99
103
 
100
104
  For example; `multigit -m commit -ab` would run `git commit -a` in each of the working trees that is branched and contains modified files.
@@ -7,7 +7,7 @@ name = "skilleter_thingy"
7
7
 
8
8
  # Version must be incremented to install updated Thingy
9
9
 
10
- version = "0.1.25"
10
+ version = "0.1.27"
11
11
 
12
12
  authors = [
13
13
  {name="John Skilleter", email="john@skilleter.org.uk"},
@@ -6,6 +6,7 @@ import os
6
6
  import sys
7
7
  import fnmatch
8
8
  import configparser
9
+ import subprocess
9
10
 
10
11
  from dataclasses import dataclass, field
11
12
 
@@ -27,6 +28,8 @@ import thingy.colour as colour
27
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
28
29
  # DONE: init function
29
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
30
33
  #
31
34
  # NOPE: Clone to have option to update - as discussed, should be part of init
32
35
  # NOPE: Dry-run option - just pass the option to the Git command
@@ -36,14 +39,12 @@ import thingy.colour as colour
36
39
  # NOPE: Use PathLib - Don't really see the need
37
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
38
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
39
44
  #
40
- # TODO: 2 .init option '--update' to update the configuration file with new working trees and remove ones that are no longer there
41
- # TODO: 2. +run command to do things other than git commands
42
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)
43
46
  # TODO: 2. select_git_repos() and +dir should use consist way of selecting repos if possible
44
47
  # TODO: 3 .init option '--set-default' to update the default branch to the current one for specified working trees
45
- # TODO: 3. Ability to read default configuration options from ~/.config/thingy/multigit.rc - these are insert before argv[1] before argparse called
46
- # TODO: 3. Command that takes partial working tree name and either returns full path or pops up window to autocomplete until single match found
47
48
  # TODO: 3. Verbose option
48
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)
49
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
@@ -66,7 +67,7 @@ DEFAULT_BRANCH = 'DEFAULT'
66
67
  # commands are parameters so we have to manually create the help and parse the command line
67
68
 
68
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]
69
- {+clone, +init, +config, +dir, +list, GIT_COMMAND} ...
70
+ {+clone, +init, +config, +dir, +list, +run, +add, GIT_COMMAND} ...
70
71
 
71
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
72
73
 
@@ -86,7 +87,7 @@ options:
86
87
  --path, -C PATH Run as if the command was started in PATH instead of the current working directory
87
88
 
88
89
  Sub-commands:
89
- {+clone, +init, +dir, +config, +list, GIT_COMMAND}
90
+ {+clone, +init, +dir, +config, +list, +run, +add, GIT_COMMAND}
90
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
91
92
  +init Build or update the configuration file using the current branch in each repo as the default branch
92
93
  +config Return the name and location of the configuration file
@@ -94,6 +95,8 @@ Sub-commands:
94
95
  +list Return a list of the top level directories of each of the Git repos
95
96
  +tag TAG Apply a configuration tag to repos filtered by the command line options (list configuration tags if no parameter specified)
96
97
  +untag TAG Remove a configuration tag to repos filtered by the command line options
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
97
100
  GIT_COMMAND Any git command, including options and parameters - this is then run in all specified working trees
98
101
 
99
102
  """
@@ -308,9 +311,37 @@ def branch_name(name, default_branch):
308
311
 
309
312
  ################################################################################
310
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
+
311
342
  def mg_clone(args, config, console):
312
343
  """Clone a repo, optionally check out a branch and attempt to read the
313
- configuration file and clone all the repos listed therein, checkouting
344
+ multigit configuration file and clone all the repos listed therein, checkouting
314
345
  the default branch in each one"""
315
346
 
316
347
  _ = console
@@ -399,29 +430,7 @@ def mg_init(args, config, console):
399
430
  repo_list.append(repo)
400
431
 
401
432
  if repo not in config:
402
- # Add a new configuration entry containing the default branch, remote origin
403
- # (if there is one) and name
404
-
405
- abs_repo_path = absolute_repo_path(args, repo)
406
-
407
- config[repo] = {}
408
-
409
- default_branch = git.branch(path=abs_repo_path)
410
-
411
- if not default_branch:
412
- colour.error(f'Unable to determine default branch in [BLUE:{repo}]', prefix=True)
413
-
414
- config[repo]['default branch'] = default_branch
415
-
416
- remote = git.remotes(path=abs_repo_path)
417
-
418
- if 'origin' in remote:
419
- config[repo]['origin'] = remote['origin']
420
- config[repo]['repo name'] = os.path.basename(remote['origin']).removesuffix('.git')
421
- else:
422
- config[repo]['repo name'] = os.path.basename(repo)
423
-
424
- colour.write(f'Added [BLUE:{repo}] with default branch [BLUE:{default_branch}]')
433
+ add_new_repo(args, config, repo)
425
434
 
426
435
  if not args.quiet:
427
436
  colour.write(cleareol=True)
@@ -444,6 +453,39 @@ def mg_init(args, config, console):
444
453
 
445
454
  ################################################################################
446
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
+
447
489
  def mg_dir(args, config, console):
448
490
  """Return the location of a working tree, given the name, or the root directory
449
491
  of the tree if not
@@ -571,12 +613,43 @@ def mg_list(args, config, console):
571
613
 
572
614
  ################################################################################
573
615
 
574
- def run_git_command(args, config, console):
616
+ def mg_run(args, config, console):
575
617
  """Run a command in each of the working trees, optionally continuing if
576
618
  there's an error"""
577
619
 
578
620
  _ = console
579
621
 
622
+ if not args.parameters:
623
+ colour.error('[BOLD:+run] command - missing parameter(s)')
624
+
625
+ # Run the command in each of the working trees
626
+
627
+ for repo in select_git_repos(args, config):
628
+ if not args.quiet:
629
+ colour.write(f'\n[BLUE:{os.path.relpath(repo.name)}]\n')
630
+
631
+ repo_path = absolute_repo_path(args, repo.name)
632
+
633
+ try:
634
+ status = subprocess.run(args.parameters, cwd=repo_path, check=False)
635
+ except FileNotFoundError:
636
+ err_msg = f'"[BLUE:{args.parameters[0]}]" - Command not found'
637
+ if args.error_continue:
638
+ colour.write(f'[RED:WARNING]: {err_msg}')
639
+ else:
640
+ colour.error(f'[RED:ERROR]: {err_msg}')
641
+ else:
642
+ if status.returncode and not args.error_continue:
643
+ sys.exit(status)
644
+
645
+ ################################################################################
646
+
647
+ def run_git_command(args, config, console):
648
+ """Run a Git command in each of the working trees, optionally continuing if
649
+ there's an error"""
650
+
651
+ _ = console
652
+
580
653
  for repo in select_git_repos(args, config):
581
654
  repo_command = [args.command]
582
655
 
@@ -585,9 +658,10 @@ def run_git_command(args, config, console):
585
658
  for cmd in args.parameters:
586
659
  repo_command.append(branch_name(cmd, repo['default branch']))
587
660
 
588
- colour.write(f'\n[BLUE:{os.path.relpath(repo.name)}]\n')
661
+ if not args.quiet:
662
+ colour.write(f'\n[BLUE:{os.path.relpath(repo.name)}]\n')
589
663
 
590
- # Run the command in the workng tree
664
+ # Run the command in the working tree
591
665
 
592
666
  repo_path = absolute_repo_path(args, repo.name)
593
667
 
@@ -680,11 +754,12 @@ def parse_command_line():
680
754
  colour.error('The "[BOLD:--path]" option takes a path parameter')
681
755
 
682
756
  try:
683
- os.chdir(arg_list.pop(0))
757
+ workingdir = arg_list.pop(0)
758
+ os.chdir(workingdir)
684
759
  except IndexError:
685
760
  colour.error('The "[BOLD:-C]" option takes a path parameter', prefix=True)
686
761
  except FileNotFoundError:
687
- colour.error('"[BOLD:--path]" - path not found', prefix=True)
762
+ colour.error(f'"[BOLD:--path]" - path "[BLUE:{workingdir}]" not found', prefix=True)
688
763
 
689
764
  elif option in ('help', 'h'):
690
765
  colour.write(HELP_INFO)
@@ -729,6 +804,8 @@ COMMANDS = {
729
804
  'tag': mg_tag,
730
805
  'untag': mg_untag,
731
806
  'list': mg_list,
807
+ 'run': mg_run,
808
+ 'add': mg_add,
732
809
  }
733
810
 
734
811
  def main():
@@ -811,6 +888,8 @@ def multigit():
811
888
 
812
889
  except git.GitError as exc:
813
890
  sys.stderr.write(exc.msg)
891
+ sys.stderr.write('\n')
892
+
814
893
  sys.exit(exc.status)
815
894
 
816
895
  ################################################################################
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skilleter_thingy
3
- Version: 0.1.25
3
+ Version: 0.1.27
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` - Clone a repo containing a multigit configuration file then clone all the repos specified in the configuration, checking out the default branch in each one.
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
 
@@ -118,6 +118,10 @@ Multigit supports a small list of subcommands, each of which are prefixed with a
118
118
 
119
119
  `+untag TAG` - Remove the tag from the specified working trees (do nothing if the tag is not applied in the first place).
120
120
 
121
+ `+run COMMAND` - Run the specified command in each of the specified working trees
122
+
123
+ `+add REPO DIR` - Clone REPO into the DIR directory and, if successful, add it to the multigit configuration
124
+
121
125
  Any command *not* prefixed with `+` is run in each of the working trees (filtered by the various multigit options) as a git command.
122
126
 
123
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.