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.

@@ -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
- # Add a new configuration entry containing the default branch, remote origin
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
- if not args.quiet:
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.26
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` - 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
 
@@ -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=ZLL0AN2ZmrWY2BPBaHsdVqqGeyk3pJo1jMFRm2zZXoU,33056
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.26.dist-info/licenses/LICENSE,sha256=ljOS4DjXvqEo5VzGfdaRwgRZPbNScGBmfwyC8PChvmQ,32422
65
- skilleter_thingy-0.1.26.dist-info/METADATA,sha256=F2AzaiFif-DiP2_J1ZKEGymC4jcf_eiQN49tKcxYpOM,30260
66
- skilleter_thingy-0.1.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
67
- skilleter_thingy-0.1.26.dist-info/entry_points.txt,sha256=mklrWFvNKw9Hyem9RG3x0PoVYjlx2fDnJ3xWMTMOmfs,2258
68
- skilleter_thingy-0.1.26.dist-info/top_level.txt,sha256=8-JhgToBBiWURunmvfpSxEvNkDHQQ7r25-aBXtZv61g,17
69
- skilleter_thingy-0.1.26.dist-info/RECORD,,
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,,