skilleter-thingy 0.0.70__tar.gz → 0.0.72__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.0.70/skilleter_thingy.egg-info → skilleter_thingy-0.0.72}/PKG-INFO +1 -2
  2. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/pyproject.toml +3 -2
  3. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/multigit.py +137 -40
  4. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/git2.py +2 -2
  5. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72/skilleter_thingy.egg-info}/PKG-INFO +1 -2
  6. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy.egg-info/entry_points.txt +1 -0
  7. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy.egg-info/requires.txt +0 -1
  8. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/LICENSE +0 -0
  9. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/README.md +0 -0
  10. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/setup.cfg +0 -0
  11. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/__init__.py +0 -0
  12. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/addpath.py +0 -0
  13. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/borger.py +0 -0
  14. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/box.py +0 -0
  15. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/console_colours.py +0 -0
  16. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/diskspacecheck.py +0 -0
  17. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/docker_purge.py +0 -0
  18. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/ffind.py +0 -0
  19. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/ggit.py +0 -0
  20. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/ggrep.py +0 -0
  21. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_br.py +0 -0
  22. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_ca.py +0 -0
  23. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_cleanup.py +0 -0
  24. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_co.py +0 -0
  25. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_common.py +0 -0
  26. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_hold.py +0 -0
  27. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_mr.py +0 -0
  28. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_parent.py +0 -0
  29. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_review.py +0 -0
  30. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_update.py +0 -0
  31. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/git_wt.py +0 -0
  32. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/gitcmp_helper.py +0 -0
  33. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/gitprompt.py +0 -0
  34. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/gl.py +0 -0
  35. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/gphotosync.py +0 -0
  36. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/linecount.py +0 -0
  37. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/moviemover.py +0 -0
  38. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/photodupe.py +0 -0
  39. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/phototidier.py +0 -0
  40. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/py_audit.py +0 -0
  41. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/readable.py +0 -0
  42. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/remdir.py +0 -0
  43. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/rmdupe.py +0 -0
  44. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/rpylint.py +0 -0
  45. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/splitpics.py +0 -0
  46. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/strreplace.py +0 -0
  47. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/sysmon.py +0 -0
  48. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/tfm.py +0 -0
  49. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/tfparse.py +0 -0
  50. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/__init__.py +0 -0
  51. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/colour.py +0 -0
  52. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/dc_curses.py +0 -0
  53. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/dc_defaults.py +0 -0
  54. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/dc_util.py +0 -0
  55. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/dircolors.py +0 -0
  56. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/docker.py +0 -0
  57. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/files.py +0 -0
  58. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/git.py +0 -0
  59. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/gitlab.py +0 -0
  60. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/path.py +0 -0
  61. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/popup.py +0 -0
  62. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/process.py +0 -0
  63. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/run.py +0 -0
  64. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/tfm_pane.py +0 -0
  65. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/tidy.py +0 -0
  66. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/thingy/venv_template.py +0 -0
  67. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/trimpath.py +0 -0
  68. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/venv_create.py +0 -0
  69. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/window_rename.py +0 -0
  70. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/xchmod.py +0 -0
  71. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy/yamlcheck.py +0 -0
  72. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy.egg-info/SOURCES.txt +0 -0
  73. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/skilleter_thingy.egg-info/dependency_links.txt +0 -0
  74. {skilleter_thingy-0.0.70 → skilleter_thingy-0.0.72}/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.0.70
3
+ Version: 0.0.72
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
@@ -18,7 +18,6 @@ Requires-Dist: pyaml
18
18
  Requires-Dist: pygit2
19
19
  Requires-Dist: python-dateutil
20
20
  Requires-Dist: requests
21
- Requires-Dist: tomlkit
22
21
 
23
22
  # Thingy
24
23
 
@@ -7,7 +7,7 @@ name = "skilleter_thingy"
7
7
 
8
8
  # Version must be incremented to install updated Thingy
9
9
 
10
- version = "0.0.70"
10
+ version = "0.0.72"
11
11
 
12
12
  authors = [
13
13
  {name="John Skilleter", email="john@skilleter.org.uk"},
@@ -34,7 +34,7 @@ dependencies = [
34
34
  "pygit2",
35
35
  "python-dateutil",
36
36
  "requests",
37
- "tomlkit",
37
+ # "tomlkit",
38
38
  ]
39
39
 
40
40
  [project.urls]
@@ -67,6 +67,7 @@ gphotosync = "skilleter_thingy:gphotosync.gphotosync"
67
67
  linecount = "skilleter_thingy:linecount.linecount"
68
68
  mg = "skilleter_thingy:mg.mg"
69
69
  moviemover = "skilleter_thingy:moviemover.moviemover"
70
+ multigit = "skilleter_thingy:multigit.multigit"
70
71
  photodupe = "skilleter_thingy:photodupe.photodupe"
71
72
  phototidier = "skilleter_thingy:phototidier.phototidier"
72
73
  py-audit = "skilleter_thingy:py_audit.py_audit"
@@ -5,8 +5,11 @@
5
5
  import os
6
6
  import sys
7
7
  import argparse
8
+ import fnmatch
9
+ import configparser
8
10
 
9
- import tomlkit
11
+ # TODO: Switch to tomlkit
12
+ from collections import defaultdict
10
13
 
11
14
  import thingy.git2 as git
12
15
  import thingy.colour as colour
@@ -17,28 +20,23 @@ import thingy.colour as colour
17
20
 
18
21
  [default]
19
22
  # Default settings
20
- default branch = name
21
23
 
22
- [repos]
24
+ [repo_path]
23
25
  name = path
24
26
  default branch = name
25
-
26
- [git-repo-location] # Either absolute or relative to the directory where the configuration file is found
27
- # Repo-specific settings to override default section
28
27
  """
29
28
 
30
- # TODO: -j option to run in parallel
29
+ # TODO: -j option to run in parallel?
31
30
  # TODO: init function
32
31
  # TODO: Use the configuration file
33
32
  # TODO: Don't use a fixed list of default branch names
34
- # TODO: Output name of each git repo as it is processed as command sits there seeming to do nothing otherwise.
33
+ # TODO: / Output name of each git repo as it is processed as command sits there seeming to do nothing otherwise.
34
+ # TODO: ? Pull/fetch - only output after running command and only if something updated
35
35
 
36
36
  ################################################################################
37
37
 
38
38
  DEFAULT_CONFIG_FILE = 'multigit.toml'
39
39
 
40
- DEFAULT_BRANCHES = ('main', 'scv-poc', 'master')
41
-
42
40
  ################################################################################
43
41
 
44
42
  def error(msg, status=1):
@@ -63,58 +61,112 @@ def show_progress(width, msg):
63
61
 
64
62
  ################################################################################
65
63
 
66
- def find_git_repos(directory):
64
+ def find_git_repos(directory, wildcard):
67
65
  """Locate and return a list of '.git' directory parent directories in the
68
- specified path"""
69
-
70
- git_repos = []
66
+ specified path.
67
+ If wildcard is not None then it is treated as a list of wildcards and
68
+ only repos matching at least one of the wildcards are returned."""
71
69
 
72
70
  for root, dirs, _ in os.walk(directory):
73
71
  if '.git' in dirs:
74
- git_repos.append(root)
75
-
76
- return git_repos
72
+ if root.startswith('./'):
73
+ root = root[2:]
74
+
75
+ if wildcard:
76
+ for card in wildcard:
77
+ if fnmatch.fnmatch(root, card):
78
+ yield root
79
+ break
80
+ else:
81
+ yield root
77
82
 
78
83
  ################################################################################
79
84
 
80
85
  def mg_init(args, config, console):
81
- """Create or update the configuration"""
82
-
83
- error('Not used - yet!')
84
-
85
- if config:
86
- print(f'Updating existing multigit configuration file - {args.config}')
87
- error('Not supported yet')
88
- else:
89
- print(f'Creating new multigit configuration file - {args.config}')
86
+ """Create or update the configuration
87
+ By default, it scans the tree for git directories and adds or updates them
88
+ in the configuration, using the current branch as the default branch. """
90
89
 
91
90
  # Search for .git directories
92
91
 
93
- git_repos = find_git_repos(args.directory)
92
+ for repo in find_git_repos(args.directory, args.repos):
93
+ if not args.quiet:
94
+ show_progress(console.columns, repo)
95
+
96
+ config[repo] = {'default branch': git.branch(path=repo)}
94
97
 
95
98
  ################################################################################
96
99
 
97
100
  def mg_status(args, config, console):
98
101
  """Report Git status for any repo that has a non-empty status"""
99
102
 
100
- for repo in find_git_repos(args.directory):
103
+ for repo in find_git_repos(args.directory, args.repos):
101
104
  if not args.quiet:
102
105
  show_progress(console.columns, repo)
103
106
 
104
107
  status = git.status(path=repo)
105
108
  branch = git.branch(path=repo)
106
109
 
107
- if status or branch not in DEFAULT_BRANCHES:
108
- if branch in DEFAULT_BRANCHES:
110
+ if status or branch != config[repo]['default branch']:
111
+ if branch == config[repo]['default branch']:
109
112
  colour.write(f'[BOLD:{repo}]')
110
113
  else:
111
114
  colour.write(f'[BOLD:{repo}] - branch: [BLUE:{branch}]')
112
115
 
116
+ staged = defaultdict(list)
117
+ unstaged = defaultdict(list)
118
+ untracked = []
119
+
113
120
  for entry in status:
114
121
  if entry[0] == '??':
115
- colour.write(f' Untracked: [BLUE:{entry[1]}]')
122
+ untracked.append(entry[1])
123
+ elif entry[0][0] == 'M':
124
+ staged['Updated'].append(entry[1])
125
+ elif entry[0][0] == 'T':
126
+ staged['Type changed'].append(entry[1])
127
+ elif entry[0][0] == 'A':
128
+ staged['Added'].append(entry[1])
129
+ elif entry[0][0] == 'D':
130
+ staged['Deleted'].append(entry[1])
131
+ elif entry[0][0] == 'R':
132
+ staged['Renamed'].append(entry[1])
133
+ elif entry[0][0] == 'C':
134
+ staged['Copied'].append(entry[1])
135
+ elif entry[0][1] == 'M':
136
+ colour.write(f' WT Updated: [BLUE:{entry[1]}]')
137
+ elif entry[0][1] == 'T':
138
+ colour.write(f' WT Type changed: [BLUE:{entry[1]}]')
139
+ elif entry[0][1] == 'D':
140
+ unstaged['Deleted'].append(entry[1])
141
+ elif entry[0][1] == 'R':
142
+ colour.write(f' WT Renamed: [BLUE:{entry[1]}]')
143
+ elif entry[0][1] == 'C':
144
+ colour.write(f' WT Copied: [BLUE:{entry[1]}]')
116
145
  else:
117
- colour.write(f' [BLUE:{entry}]')
146
+ staged['Other'].append(f' {entry[0]}: [BLUE:{entry[1]}]')
147
+
148
+ if untracked:
149
+ colour.write()
150
+ colour.write('Untracked files:')
151
+
152
+ for git_object in untracked:
153
+ colour.write(f' [BLUE:{git_object}]')
154
+
155
+ if staged:
156
+ colour.write()
157
+ colour.write('Changes staged for commit:')
158
+
159
+ for item in staged:
160
+ for git_object in staged[item]:
161
+ colour.write(f' {item}: [BLUE:{git_object}]')
162
+
163
+ if unstaged:
164
+ colour.write()
165
+ colour.write('Changes not staged for commit:')
166
+
167
+ for item in unstaged:
168
+ for git_object in unstaged[item]:
169
+ colour.write(f' {item}: [BLUE:{git_object}]')
118
170
 
119
171
  colour.write()
120
172
 
@@ -123,10 +175,12 @@ def mg_status(args, config, console):
123
175
  def mg_fetch(args, config, console):
124
176
  """Run git fetch everywhere"""
125
177
 
126
- for repo in find_git_repos(args.directory):
178
+ for repo in find_git_repos(args.directory, args.repos):
127
179
  if not args.quiet:
128
180
  show_progress(console.columns, repo)
129
181
 
182
+ colour.write(f'Fetching updates for [BLUE:{repo}]')
183
+
130
184
  result = git.fetch(path=repo)
131
185
 
132
186
  if result:
@@ -144,10 +198,12 @@ def mg_fetch(args, config, console):
144
198
  def mg_pull(args, config, console):
145
199
  """Run git pull everywhere"""
146
200
 
147
- for repo in find_git_repos(args.directory):
201
+ for repo in find_git_repos(args.directory, args.repos):
148
202
  if not args.quiet:
149
203
  show_progress(console.columns, repo)
150
204
 
205
+ colour.write(f'Pulling updates for [BLUE:{repo}]')
206
+
151
207
  try:
152
208
  result = git.pull(path=repo)
153
209
  except git.GitError as exc:
@@ -173,7 +229,26 @@ def mg_push(args, config, console):
173
229
  # TODO: Add option for force-push?
174
230
  # TODO: Add option for manual confirmation?
175
231
 
176
- pass
232
+ ################################################################################
233
+
234
+ def mg_checkout(args, config, console):
235
+ """Run git checkout everywhere.
236
+ By default it just checks out the specified branch (or the default branch)
237
+ if the branch exists in the repo.
238
+ If the 'create' option is specified then branch is created"""
239
+
240
+ # TODO: Add --create handling
241
+
242
+ for repo in find_git_repos(args.directory, args.repos):
243
+ if not args.quiet:
244
+ show_progress(console.columns, repo)
245
+
246
+ branch = args.branch or config[repo]['default branch']
247
+
248
+ if git.branch(path=repo) != branch:
249
+ console.write(f'Checking out [BLUE:{branch}] in [BLUE:{repo}]')
250
+
251
+ git.checkout(branch, path=repo)
177
252
 
178
253
  ################################################################################
179
254
 
@@ -186,6 +261,7 @@ def main():
186
261
  'fetch': mg_fetch,
187
262
  'pull': mg_pull,
188
263
  'push': mg_push,
264
+ 'checkout': mg_checkout,
189
265
  }
190
266
 
191
267
  # Parse args in the form COMMAND OPTIONS SUBCOMMAND SUBCOMMAND_OPTIONS PARAMETERS
@@ -198,25 +274,40 @@ def main():
198
274
  parser.add_argument('--quiet', '-q', action='store_true', help='Minimal console output')
199
275
  parser.add_argument('--config', '-c', action='store', default=DEFAULT_CONFIG_FILE, help=f'The configuration file (defaults to {DEFAULT_CONFIG_FILE})')
200
276
  parser.add_argument('--directory', '--dir', action='store', default='.', help='The top-level directory of the multigit tree (defaults to the current directory)')
277
+ parser.add_argument('--repos', '-r', action='append', default=None, help='The list of repo names to work on (defaults to all repos and can contain shell wildcards)')
201
278
 
202
279
  subparsers = parser.add_subparsers(dest='command')
203
280
 
204
281
  # Subcommands - currently just init, status, fetch, pull, push, with more to come
205
282
 
206
- parser_init = subparsers.add_parser('init', help='')
283
+ parser_init = subparsers.add_parser('init', help='Build or update the configuration file using the current branch in each repo as the default branch')
207
284
 
208
- parser_status = subparsers.add_parser('status', help='Report git status in every repo that has one')
285
+ parser_status = subparsers.add_parser('status', help='Report git status in every repo that has something to report')
209
286
  parser_fetch = subparsers.add_parser('fetch', help='Run git fetch in every repo')
210
287
  parser_pull = subparsers.add_parser('pull', help='Run git pull in every repo')
211
288
  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')
212
289
 
290
+ parser_checkout = subparsers.add_parser('checkout', help='Checkout the specified branch')
291
+ parser_checkout.add_argument('--create', action='store_true', help='Create the specified branch and check it out')
292
+ parser_checkout.add_argument('branch', nargs='?', default=None, action='store', help='The branch name to check out (defaults to the default branch)')
293
+
213
294
  # Parse the command line
214
295
 
215
296
  args = parser.parse_args()
216
297
 
298
+ # Basic error checking
299
+
300
+ if not args.command:
301
+ error('No command specified')
302
+
303
+ # 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
304
+
217
305
  # If the configuration file exists, read it
218
306
 
219
- config = tomlkit.loads(args.config) if os.path.isfile(args.config) else None
307
+ config = configparser.ConfigParser()
308
+
309
+ if os.path.isfile(args.config):
310
+ config.read(args.config)
220
311
 
221
312
  # Get the console size
222
313
 
@@ -226,9 +317,15 @@ def main():
226
317
 
227
318
  commands[args.command](args, config, console)
228
319
 
320
+ # Save the updated configuration file
321
+
322
+ if config:
323
+ with open(args.config, 'w') as configfile:
324
+ config.write(configfile)
325
+
229
326
  ################################################################################
230
327
 
231
- def mg():
328
+ def multigit():
232
329
  """Entry point"""
233
330
 
234
331
  try:
@@ -241,4 +338,4 @@ def mg():
241
338
  ################################################################################
242
339
 
243
340
  if __name__ == '__main__':
244
- mg()
341
+ multigit()
@@ -203,7 +203,7 @@ def pull(repo=None, all=False, path=None):
203
203
 
204
204
  ################################################################################
205
205
 
206
- def checkout(branch, create=False):
206
+ def checkout(branch, create=False, path=None):
207
207
  """ Checkout a branch (optionally creating it) """
208
208
 
209
209
  cmd = ['checkout']
@@ -213,7 +213,7 @@ def checkout(branch, create=False):
213
213
 
214
214
  cmd.append(branch)
215
215
 
216
- return git(cmd)
216
+ return git(cmd, path=path)
217
217
 
218
218
  ################################################################################
219
219
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: skilleter_thingy
3
- Version: 0.0.70
3
+ Version: 0.0.72
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
@@ -18,7 +18,6 @@ Requires-Dist: pyaml
18
18
  Requires-Dist: pygit2
19
19
  Requires-Dist: python-dateutil
20
20
  Requires-Dist: requests
21
- Requires-Dist: tomlkit
22
21
 
23
22
  # Thingy
24
23
 
@@ -25,6 +25,7 @@ gphotosync = skilleter_thingy:gphotosync.gphotosync
25
25
  linecount = skilleter_thingy:linecount.linecount
26
26
  mg = skilleter_thingy:mg.mg
27
27
  moviemover = skilleter_thingy:moviemover.moviemover
28
+ multigit = skilleter_thingy:multigit.multigit
28
29
  photodupe = skilleter_thingy:photodupe.photodupe
29
30
  phototidier = skilleter_thingy:phototidier.phototidier
30
31
  py-audit = skilleter_thingy:py_audit.py_audit
@@ -6,4 +6,3 @@ pyaml
6
6
  pygit2
7
7
  python-dateutil
8
8
  requests
9
- tomlkit