skilleter-thingy 0.1.2__tar.gz → 0.1.3__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.
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/PKG-INFO +5 -1
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/README.md +4 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/pyproject.toml +1 -1
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/multigit.py +155 -47
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/git2.py +3 -3
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/PKG-INFO +5 -1
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/LICENSE +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/setup.cfg +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/__init__.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/addpath.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/borger.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/console_colours.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/diskspacecheck.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/docker_purge.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/ffind.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/ggit.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/ggrep.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_br.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_ca.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_cleanup.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_co.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_common.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_hold.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_mr.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_parent.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_review.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_update.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/git_wt.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/gitcmp_helper.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/gitprompt.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/gl.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/gphotosync.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/linecount.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/moviemover.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/photodupe.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/phototidier.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/py_audit.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/readable.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/remdir.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/rmdupe.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/rpylint.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/splitpics.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/strreplace.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/sysmon.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/tfm.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/tfparse.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/__init__.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/colour.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/dc_curses.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/dc_defaults.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/dc_util.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/dircolors.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/docker.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/files.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/git.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/gitlab.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/path.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/popup.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/process.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/run.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/tfm_pane.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/tidy.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/thingy/venv_template.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/trimpath.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/venv_create.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/window_rename.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/xchmod.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy/yamlcheck.py +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/SOURCES.txt +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/dependency_links.txt +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/entry_points.txt +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/requires.txt +0 -0
- {skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: skilleter_thingy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
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
|
|
@@ -89,6 +89,8 @@ The command takes a number of options that can be used to select the list of wor
|
|
|
89
89
|
|
|
90
90
|
`--tag TAG` / `-t TAG` Run only in working trees that are tagged with the specified tag
|
|
91
91
|
|
|
92
|
+
`--subdir` / `-s` Run only in working trees that are in the current directory tree.
|
|
93
|
+
|
|
92
94
|
These options are AND-ed together, so specifying `--modified --branched --tag WOMBAT` will select only working trees that are modified AND branched AND tagged with `WOMBAT`, but the parameters to the `--repos` and `--tag` options are OR-ed together, so specifying `--tag WOMBAT --tag EMU` will select repos that are tagged as `WOMBAT` *OR* `EMU`.
|
|
93
95
|
|
|
94
96
|
Multigit tags are stored in the configuration file, not within the working tree and each working tree can have multiple tags.
|
|
@@ -97,6 +99,8 @@ Multigit tags are stored in the configuration file, not within the working tree
|
|
|
97
99
|
|
|
98
100
|
Multigit supports a small list of subcommands, each of which are prefixed with a `+` to distinguish them from Git commands:
|
|
99
101
|
|
|
102
|
+
`+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.
|
|
103
|
+
|
|
100
104
|
`+init` - Create or update the configuration file
|
|
101
105
|
|
|
102
106
|
`+dir` - Given the name of a working tree, output the location within the multigit tree of that working tree if the name matches uniquely, or the name of the directory where the multigit configuration file resides if no parameter is specified.
|
|
@@ -67,6 +67,8 @@ The command takes a number of options that can be used to select the list of wor
|
|
|
67
67
|
|
|
68
68
|
`--tag TAG` / `-t TAG` Run only in working trees that are tagged with the specified tag
|
|
69
69
|
|
|
70
|
+
`--subdir` / `-s` Run only in working trees that are in the current directory tree.
|
|
71
|
+
|
|
70
72
|
These options are AND-ed together, so specifying `--modified --branched --tag WOMBAT` will select only working trees that are modified AND branched AND tagged with `WOMBAT`, but the parameters to the `--repos` and `--tag` options are OR-ed together, so specifying `--tag WOMBAT --tag EMU` will select repos that are tagged as `WOMBAT` *OR* `EMU`.
|
|
71
73
|
|
|
72
74
|
Multigit tags are stored in the configuration file, not within the working tree and each working tree can have multiple tags.
|
|
@@ -75,6 +77,8 @@ Multigit tags are stored in the configuration file, not within the working tree
|
|
|
75
77
|
|
|
76
78
|
Multigit supports a small list of subcommands, each of which are prefixed with a `+` to distinguish them from Git commands:
|
|
77
79
|
|
|
80
|
+
`+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.
|
|
81
|
+
|
|
78
82
|
`+init` - Create or update the configuration file
|
|
79
83
|
|
|
80
84
|
`+dir` - Given the name of a working tree, output the location within the multigit tree of that working tree if the name matches uniquely, or the name of the directory where the multigit configuration file resides if no parameter is specified.
|
|
@@ -14,6 +14,7 @@ import thingy.colour as colour
|
|
|
14
14
|
|
|
15
15
|
################################################################################
|
|
16
16
|
|
|
17
|
+
# DONE: ***MUST use relative paths in config file, or we can't store in git and clone and use somewhere else!***
|
|
17
18
|
# DONE: / Output name of each working tree as it is processed as command sits there seeming to do nothing otherwise.
|
|
18
19
|
# DONE: Better error-handling - e.g. continue/abort option after failure in one working tree
|
|
19
20
|
# DONE: Currently doesn't handle single letter options in concatenated form - e.g. -dv
|
|
@@ -21,29 +22,30 @@ import thingy.colour as colour
|
|
|
21
22
|
# DONE: Don't use a fixed list of default branch names
|
|
22
23
|
# DONE: If the config file isn't in the current directory then search up the directory tree for it but run in the current directory
|
|
23
24
|
# DONE: Use the configuration file
|
|
25
|
+
# DONE: When specifying list of working trees, if name doesn't contain '/' prefix it with '*'?
|
|
24
26
|
# 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
|
|
25
27
|
# DONE: init function
|
|
28
|
+
# NOPE: Clone to have option to update - as discussed, should be part of init
|
|
26
29
|
# NOPE: Dry-run option - just pass the option to the Git command
|
|
27
30
|
# NOPE: Is it going to be a problem if the same repo is checked out twice or more in the same workspace - user problem
|
|
28
31
|
# NOPE: Pull/fetch - only output after running command and only if something updated
|
|
29
32
|
# NOPE: Switch to tomlkit
|
|
30
|
-
# TODO:
|
|
31
|
-
# TODO:
|
|
32
|
-
# TODO:
|
|
33
|
-
# TODO:
|
|
34
|
-
# TODO:
|
|
35
|
-
# TODO:
|
|
36
|
-
#
|
|
37
|
-
# TODO:
|
|
38
|
-
# TODO:
|
|
39
|
-
# TODO:
|
|
40
|
-
# TODO:
|
|
41
|
-
# TODO:
|
|
42
|
-
# TODO:
|
|
43
|
-
# TODO:
|
|
44
|
-
# TODO:
|
|
45
|
-
# TODO: Use
|
|
46
|
-
# TODO: Shell autocomplete for +dir
|
|
33
|
+
# TODO: 2 .init option '--update' to update the configuration file with new working trees and remove ones that are no longer there
|
|
34
|
+
# TODO: 2. +run command to do things other than git commands
|
|
35
|
+
# 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)
|
|
36
|
+
# TODO: 2. select_git_repos() and +dir should use consist way of selecting repos if possible
|
|
37
|
+
# TODO: 3 .init option '--set-default' to update the default branch to the current one for specified working trees
|
|
38
|
+
# TODO: 3. Ability to read default configuration options from ~/.config/thingy/multigit.rc - these are insert before argv[1] before argparse called
|
|
39
|
+
# TODO: 3. Command that takes partial working tree name and either returns full path or pops up window to autocomplete until single match found
|
|
40
|
+
# TODO: 3. Verbose option
|
|
41
|
+
# 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)
|
|
42
|
+
# TODO: 4. Option to +dir to return all matches so that caller can select one they want
|
|
43
|
+
# TODO: 4. Shell autocomplete for +dir
|
|
44
|
+
# TODO: 5. -j option to run in parallel - yes, but it will only work with non-interactive Git commands
|
|
45
|
+
# TODO: 5. Consistent colours in output
|
|
46
|
+
# TODO: 6. Use PathLib
|
|
47
|
+
# TODO: 6. 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
|
|
48
|
+
# TODO: 7. Use pygit2 directly
|
|
47
49
|
################################################################################
|
|
48
50
|
|
|
49
51
|
DEFAULT_CONFIG_FILE = 'multigit.toml'
|
|
@@ -54,9 +56,11 @@ DEFAULT_CONFIG_FILE = 'multigit.toml'
|
|
|
54
56
|
DEFAULT_BRANCH = 'DEFAULT'
|
|
55
57
|
|
|
56
58
|
################################################################################
|
|
59
|
+
# Command line help - we aren't using argparse since it isn't flexible enough to handle arbtirary git
|
|
60
|
+
# commands are parameters so we have to manually create the help and parse the command line
|
|
57
61
|
|
|
58
62
|
HELP_INFO = """usage: multigit [-h] [--verbose] [--quiet] [--config CONFIG] [--repos REPOS] [--modified] [--branched] [--sub] [--tag TAGS]
|
|
59
|
-
{+init, +config, +dir, GIT_COMMAND} ...
|
|
63
|
+
{+clone, +init, +config, +dir, GIT_COMMAND} ...
|
|
60
64
|
|
|
61
65
|
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
|
|
62
66
|
|
|
@@ -71,11 +75,12 @@ options:
|
|
|
71
75
|
--modified, -m Select repos that have local modifications
|
|
72
76
|
--branched, -b Select repos that do not have the default branch checked out
|
|
73
77
|
--tag TAG, -t TAG Select repos that have the specified tag (can be issued multiple times on the command line)
|
|
74
|
-
--continue, -C Continue if a git command returns an error (by default, executation terminates when a command fails)
|
|
75
78
|
--sub, -s Select only the repos in the current directory and subdirectories
|
|
79
|
+
--continue, -C Continue if a git command returns an error (by default, executation terminates when a command fails)
|
|
76
80
|
|
|
77
81
|
Sub-commands:
|
|
78
|
-
{+init,+dir,+config,GIT_COMMAND}
|
|
82
|
+
{+clone, +init,+dir,+config, GIT_COMMAND}
|
|
83
|
+
+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
|
|
79
84
|
+init Build or update the configuration file using the current branch in each repo as the default branch
|
|
80
85
|
+config Return the name and location of the configuration file
|
|
81
86
|
+dir Return the location of a working tree, given the repo name, or if no parameter specified, the root directory of the multigit tree
|
|
@@ -136,6 +141,14 @@ def error(msg, status=1):
|
|
|
136
141
|
|
|
137
142
|
################################################################################
|
|
138
143
|
|
|
144
|
+
def absolute_repo_path(args, relative_path=''):
|
|
145
|
+
"""Given a path relative to the multigit configuration file, return
|
|
146
|
+
the absolute path thereto"""
|
|
147
|
+
|
|
148
|
+
return os.path.join(os.path.dirname(args.configuration_file), relative_path)
|
|
149
|
+
|
|
150
|
+
################################################################################
|
|
151
|
+
|
|
139
152
|
def find_configuration(default_config_file):
|
|
140
153
|
"""If the configuration file name has path elements, try and read it, otherwise
|
|
141
154
|
search up the directory tree looking for the configuration file.
|
|
@@ -157,7 +170,8 @@ def find_configuration(default_config_file):
|
|
|
157
170
|
################################################################################
|
|
158
171
|
|
|
159
172
|
def show_progress(width, msg):
|
|
160
|
-
"""Show a single line progress message
|
|
173
|
+
"""Show a single line progress message without moving the cursor to the next
|
|
174
|
+
line."""
|
|
161
175
|
|
|
162
176
|
colour.write(msg[:width-1], newline=False, cleareol=True, cr=True)
|
|
163
177
|
|
|
@@ -176,20 +190,19 @@ def find_working_trees(args):
|
|
|
176
190
|
|
|
177
191
|
for root, dirs, _ in os.walk(os.path.dirname(args.configuration_file)):
|
|
178
192
|
if '.git' in dirs:
|
|
179
|
-
|
|
180
|
-
root = root[2:]
|
|
193
|
+
relative_path = os.path.relpath(root)
|
|
181
194
|
|
|
182
195
|
if args.repos:
|
|
183
196
|
for card in args.repos:
|
|
184
|
-
if fnmatch.fnmatch(
|
|
185
|
-
if
|
|
186
|
-
yield
|
|
187
|
-
repos.add(
|
|
197
|
+
if fnmatch.fnmatch(relative_path, card):
|
|
198
|
+
if relative_path not in repos:
|
|
199
|
+
yield relative_path
|
|
200
|
+
repos.add(relative_path)
|
|
188
201
|
break
|
|
189
202
|
else:
|
|
190
|
-
if
|
|
191
|
-
yield
|
|
192
|
-
repos.add(
|
|
203
|
+
if relative_path not in repos:
|
|
204
|
+
yield relative_path
|
|
205
|
+
repos.add(relative_path)
|
|
193
206
|
|
|
194
207
|
################################################################################
|
|
195
208
|
|
|
@@ -250,7 +263,7 @@ def select_git_repos(args, config):
|
|
|
250
263
|
# If subdirectories specified, only match if the repo is in the current directory tree
|
|
251
264
|
|
|
252
265
|
if matching and args.subdirectories:
|
|
253
|
-
repo_path_rel = os.path.relpath(repo_path)
|
|
266
|
+
repo_path_rel = os.path.relpath(absolute_repo_path(args, repo_path))
|
|
254
267
|
|
|
255
268
|
if repo_path_rel == '..' or repo_path_rel.startswith('../'):
|
|
256
269
|
matching = False
|
|
@@ -269,6 +282,77 @@ def branch_name(name, default_branch):
|
|
|
269
282
|
|
|
270
283
|
################################################################################
|
|
271
284
|
|
|
285
|
+
def mg_clone(args, config, console):
|
|
286
|
+
"""Clone a repo, optionally check out a branch and attempt to read the
|
|
287
|
+
configuration file and clone all the repos listed therein, checkouting
|
|
288
|
+
the default branch in each one"""
|
|
289
|
+
|
|
290
|
+
_ = console
|
|
291
|
+
|
|
292
|
+
# Sanity checks
|
|
293
|
+
|
|
294
|
+
if not args.parameters:
|
|
295
|
+
error('The "clone" subcommand takes 1 or 2 parameters - the repo to clone and, optionally, the branch to check out')
|
|
296
|
+
|
|
297
|
+
if args.branched or args.modified:
|
|
298
|
+
error('The "modified" and "branched" options cannot be used with the "clone" subcommand')
|
|
299
|
+
|
|
300
|
+
# Destination directory is the last portion of the repo URL with the extension removed
|
|
301
|
+
|
|
302
|
+
directory = os.path.splitext(os.path.basename(args.parameters[0]))[0]
|
|
303
|
+
|
|
304
|
+
if os.path.exists(directory):
|
|
305
|
+
if os.path.isdir(directory):
|
|
306
|
+
error(f'The "[BLUE:{directory}]" directory already exists')
|
|
307
|
+
else:
|
|
308
|
+
error(f'[BLUE:{directory}]" already exists')
|
|
309
|
+
|
|
310
|
+
# Clone the repo and chdir into it
|
|
311
|
+
|
|
312
|
+
if not args.quiet:
|
|
313
|
+
colour.write(f'Cloning [BOLD:{args.parameters[0]}] into [BLUE:{directory}]')
|
|
314
|
+
|
|
315
|
+
git.clone(args.parameters[0], path=directory)
|
|
316
|
+
|
|
317
|
+
os.chdir(directory)
|
|
318
|
+
|
|
319
|
+
# Optionally checkout a branch, if specified
|
|
320
|
+
|
|
321
|
+
if len(args.parameters) > 1:
|
|
322
|
+
git.checkout(args.parameters[1])
|
|
323
|
+
|
|
324
|
+
# Open the configuration file in the repo (if no configuration file has been specified, use the default)
|
|
325
|
+
|
|
326
|
+
if not args.configuration_file:
|
|
327
|
+
args.configuration_file = args.default_configuration_file
|
|
328
|
+
|
|
329
|
+
if not os.path.isfile(args.configuration_file):
|
|
330
|
+
error(f'Cannot find the configuration file: [BOLD:{args.default_configuration_file}]')
|
|
331
|
+
|
|
332
|
+
config.read(args.configuration_file)
|
|
333
|
+
|
|
334
|
+
# Now iterate through the repos, creating directories and cloning them and checking
|
|
335
|
+
# out the default branch
|
|
336
|
+
|
|
337
|
+
for repo in select_git_repos(args, config):
|
|
338
|
+
if repo.name != '.':
|
|
339
|
+
directory = os.path.dirname(repo.name)
|
|
340
|
+
|
|
341
|
+
if directory:
|
|
342
|
+
os.makedirs(directory, exist_ok=True)
|
|
343
|
+
|
|
344
|
+
if not args.quiet:
|
|
345
|
+
colour.write(f'Cloning [BOLD:{repo["origin"]}] into [BLUE:{directory}]')
|
|
346
|
+
|
|
347
|
+
git.clone(repo['origin'], path=repo.name)
|
|
348
|
+
|
|
349
|
+
if not args.quiet:
|
|
350
|
+
colour.write(f' Checking out [BLUE:{repo["default branch"]}]')
|
|
351
|
+
|
|
352
|
+
git.checkout(repo['default branch'], path=repo.name)
|
|
353
|
+
|
|
354
|
+
################################################################################
|
|
355
|
+
|
|
272
356
|
def mg_init(args, config, console):
|
|
273
357
|
"""Create or update the configuration
|
|
274
358
|
By default, it scans the tree for git directories and adds or updates them
|
|
@@ -289,6 +373,9 @@ def mg_init(args, config, console):
|
|
|
289
373
|
repo_list.append(repo)
|
|
290
374
|
|
|
291
375
|
if repo not in config:
|
|
376
|
+
# Add a new configuration entry containing the default branch, remote origin
|
|
377
|
+
# and name
|
|
378
|
+
|
|
292
379
|
default_branch = git.branch(path=repo)
|
|
293
380
|
|
|
294
381
|
config[repo] = {
|
|
@@ -331,14 +418,19 @@ def mg_dir(args, config, console):
|
|
|
331
418
|
of the tree if not
|
|
332
419
|
Returns an error unless there is a unique match"""
|
|
333
420
|
|
|
334
|
-
# DONE: Should return location relative to the current directory or as absolute path
|
|
335
|
-
|
|
336
421
|
_ = console
|
|
337
422
|
_ = config
|
|
338
423
|
|
|
339
424
|
if len(args.parameters) > 1:
|
|
340
425
|
error('The +dir command takes no more than one parameter - the name of the working tree to search for')
|
|
341
|
-
|
|
426
|
+
|
|
427
|
+
if args.modified or args.branched or args.tag or args.subdirectories:
|
|
428
|
+
error('The "--tag", "--modified" "--sub", and "--branched" options cannot be used with the "dir" subcommand')
|
|
429
|
+
|
|
430
|
+
# If a parameter is specified, look for matches, otherwise just return the location of the
|
|
431
|
+
# configuration file
|
|
432
|
+
|
|
433
|
+
if args.parameters:
|
|
342
434
|
location = []
|
|
343
435
|
wild_prefix_location = []
|
|
344
436
|
wild_location = []
|
|
@@ -377,7 +469,8 @@ def mg_dir(args, config, console):
|
|
|
377
469
|
dest_list = "\n\t".join([os.path.relpath(d) for d in destination])
|
|
378
470
|
error(f'Multiple matches with [BLUE:{search_name}]: \n\t{dest_list}')
|
|
379
471
|
|
|
380
|
-
colour.write(
|
|
472
|
+
colour.write(absolute_repo_path(args, destination[0]))
|
|
473
|
+
|
|
381
474
|
else:
|
|
382
475
|
colour.write(os.path.dirname(args.configuration_file))
|
|
383
476
|
|
|
@@ -445,17 +538,23 @@ def run_git_command(args, config, console):
|
|
|
445
538
|
"""Run a command in each of the working trees, optionally continuing if
|
|
446
539
|
there's an error"""
|
|
447
540
|
|
|
448
|
-
_ = config
|
|
449
541
|
_ = console
|
|
450
542
|
|
|
451
543
|
for repo in select_git_repos(args, config):
|
|
452
544
|
repo_command = [args.command]
|
|
545
|
+
|
|
546
|
+
# Replace 'DEFAULT' in the command with the default branch in the repo
|
|
547
|
+
|
|
453
548
|
for cmd in args.parameters:
|
|
454
549
|
repo_command.append(branch_name(cmd, repo['default branch']))
|
|
455
550
|
|
|
456
551
|
colour.write(f'\n[BOLD:{os.path.relpath(repo.name)}]\n')
|
|
457
552
|
|
|
458
|
-
|
|
553
|
+
# Run the command in the workng tree
|
|
554
|
+
|
|
555
|
+
repo_path = absolute_repo_path(args, repo.name)
|
|
556
|
+
|
|
557
|
+
_, status = git.git_run_status(repo_command, path=repo_path, redirect=False)
|
|
459
558
|
|
|
460
559
|
if status and not args.error_continue:
|
|
461
560
|
sys.exit(status)
|
|
@@ -479,7 +578,7 @@ def parse_command_line():
|
|
|
479
578
|
for c in arg[1:]:
|
|
480
579
|
argv.append('-' + c)
|
|
481
580
|
|
|
482
|
-
# Parse the command line
|
|
581
|
+
# Parse the command line, setting options in the args dataclass appropriately
|
|
483
582
|
|
|
484
583
|
i = 1
|
|
485
584
|
while i < len(argv):
|
|
@@ -525,7 +624,7 @@ def parse_command_line():
|
|
|
525
624
|
args.error_continue = True
|
|
526
625
|
|
|
527
626
|
elif param in ('--help', '-h'):
|
|
528
|
-
|
|
627
|
+
colour.write(HELP_INFO)
|
|
529
628
|
sys.exit(0)
|
|
530
629
|
|
|
531
630
|
elif param[0] == '-':
|
|
@@ -549,8 +648,12 @@ def parse_command_line():
|
|
|
549
648
|
except IndexError:
|
|
550
649
|
error('Missing command')
|
|
551
650
|
|
|
651
|
+
# Save the command parameters
|
|
652
|
+
|
|
552
653
|
args.parameters = argv[i+1:]
|
|
553
654
|
|
|
655
|
+
# Locate the configuration file
|
|
656
|
+
|
|
554
657
|
args.configuration_file = find_configuration(args.default_configuration_file)
|
|
555
658
|
|
|
556
659
|
return args
|
|
@@ -558,16 +661,20 @@ def parse_command_line():
|
|
|
558
661
|
################################################################################
|
|
559
662
|
|
|
560
663
|
COMMANDS = {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
664
|
+
'clone': mg_clone,
|
|
665
|
+
'init': mg_init,
|
|
666
|
+
'dir': mg_dir,
|
|
667
|
+
'config': mg_config,
|
|
668
|
+
'tag': mg_tag,
|
|
669
|
+
'untag': mg_untag,
|
|
566
670
|
}
|
|
567
671
|
|
|
568
672
|
def main():
|
|
569
673
|
"""Main function"""
|
|
570
674
|
|
|
675
|
+
# Parse the command line and santity check the command to run
|
|
676
|
+
# (if it is an external command we let git worry about it)
|
|
677
|
+
|
|
571
678
|
args = parse_command_line()
|
|
572
679
|
|
|
573
680
|
if args.internal_command and args.command not in COMMANDS:
|
|
@@ -582,12 +689,13 @@ def main():
|
|
|
582
689
|
# Otherwise, fail if we can't find the configuration file.
|
|
583
690
|
|
|
584
691
|
if not args.configuration_file:
|
|
585
|
-
if args.internal_command
|
|
586
|
-
args.
|
|
692
|
+
if args.internal_command:
|
|
693
|
+
if args.command == 'init':
|
|
694
|
+
args.configuration_file = os.path.abspath(args.default_configuration_file)
|
|
587
695
|
else:
|
|
588
696
|
error('Cannot locate configuration file')
|
|
589
697
|
|
|
590
|
-
if os.path.isfile(args.configuration_file):
|
|
698
|
+
if args.configuration_file and os.path.isfile(args.configuration_file):
|
|
591
699
|
config.read(args.configuration_file)
|
|
592
700
|
|
|
593
701
|
# Get the console size
|
|
@@ -109,13 +109,13 @@ def git_run_status(cmd, stdout=None, stderr=None, path=None, redirect=True):
|
|
|
109
109
|
|
|
110
110
|
################################################################################
|
|
111
111
|
|
|
112
|
-
def clone(reponame,
|
|
112
|
+
def clone(reponame, path=None):
|
|
113
113
|
""" Clone a repo """
|
|
114
114
|
|
|
115
115
|
cmd = ['clone', reponame]
|
|
116
116
|
|
|
117
|
-
if
|
|
118
|
-
cmd.append(
|
|
117
|
+
if path:
|
|
118
|
+
cmd.append(path)
|
|
119
119
|
|
|
120
120
|
return git(cmd)
|
|
121
121
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: skilleter_thingy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
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
|
|
@@ -89,6 +89,8 @@ The command takes a number of options that can be used to select the list of wor
|
|
|
89
89
|
|
|
90
90
|
`--tag TAG` / `-t TAG` Run only in working trees that are tagged with the specified tag
|
|
91
91
|
|
|
92
|
+
`--subdir` / `-s` Run only in working trees that are in the current directory tree.
|
|
93
|
+
|
|
92
94
|
These options are AND-ed together, so specifying `--modified --branched --tag WOMBAT` will select only working trees that are modified AND branched AND tagged with `WOMBAT`, but the parameters to the `--repos` and `--tag` options are OR-ed together, so specifying `--tag WOMBAT --tag EMU` will select repos that are tagged as `WOMBAT` *OR* `EMU`.
|
|
93
95
|
|
|
94
96
|
Multigit tags are stored in the configuration file, not within the working tree and each working tree can have multiple tags.
|
|
@@ -97,6 +99,8 @@ Multigit tags are stored in the configuration file, not within the working tree
|
|
|
97
99
|
|
|
98
100
|
Multigit supports a small list of subcommands, each of which are prefixed with a `+` to distinguish them from Git commands:
|
|
99
101
|
|
|
102
|
+
`+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.
|
|
103
|
+
|
|
100
104
|
`+init` - Create or update the configuration file
|
|
101
105
|
|
|
102
106
|
`+dir` - Given the name of a working tree, output the location within the multigit tree of that working tree if the name matches uniquely, or the name of the directory where the multigit configuration file resides if no parameter is specified.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{skilleter_thingy-0.1.2 → skilleter_thingy-0.1.3}/skilleter_thingy.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|