skilleter-thingy 0.0.22__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.

Files changed (67) hide show
  1. skilleter_thingy/__init__.py +0 -0
  2. skilleter_thingy/addpath.py +107 -0
  3. skilleter_thingy/aws.py +548 -0
  4. skilleter_thingy/borger.py +269 -0
  5. skilleter_thingy/colour.py +213 -0
  6. skilleter_thingy/console_colours.py +63 -0
  7. skilleter_thingy/dc_curses.py +278 -0
  8. skilleter_thingy/dc_defaults.py +221 -0
  9. skilleter_thingy/dc_util.py +50 -0
  10. skilleter_thingy/dircolors.py +308 -0
  11. skilleter_thingy/diskspacecheck.py +67 -0
  12. skilleter_thingy/docker.py +95 -0
  13. skilleter_thingy/docker_purge.py +113 -0
  14. skilleter_thingy/ffind.py +536 -0
  15. skilleter_thingy/files.py +142 -0
  16. skilleter_thingy/ggit.py +90 -0
  17. skilleter_thingy/ggrep.py +154 -0
  18. skilleter_thingy/git.py +1368 -0
  19. skilleter_thingy/git2.py +1307 -0
  20. skilleter_thingy/git_br.py +180 -0
  21. skilleter_thingy/git_ca.py +142 -0
  22. skilleter_thingy/git_cleanup.py +287 -0
  23. skilleter_thingy/git_co.py +220 -0
  24. skilleter_thingy/git_common.py +61 -0
  25. skilleter_thingy/git_hold.py +154 -0
  26. skilleter_thingy/git_mr.py +92 -0
  27. skilleter_thingy/git_parent.py +77 -0
  28. skilleter_thingy/git_review.py +1416 -0
  29. skilleter_thingy/git_update.py +385 -0
  30. skilleter_thingy/git_wt.py +96 -0
  31. skilleter_thingy/gitcmp_helper.py +322 -0
  32. skilleter_thingy/gitlab.py +193 -0
  33. skilleter_thingy/gitprompt.py +274 -0
  34. skilleter_thingy/gl.py +174 -0
  35. skilleter_thingy/gphotosync.py +610 -0
  36. skilleter_thingy/linecount.py +155 -0
  37. skilleter_thingy/logger.py +112 -0
  38. skilleter_thingy/moviemover.py +133 -0
  39. skilleter_thingy/path.py +156 -0
  40. skilleter_thingy/photodupe.py +110 -0
  41. skilleter_thingy/phototidier.py +248 -0
  42. skilleter_thingy/popup.py +87 -0
  43. skilleter_thingy/process.py +112 -0
  44. skilleter_thingy/py_audit.py +131 -0
  45. skilleter_thingy/readable.py +270 -0
  46. skilleter_thingy/remdir.py +126 -0
  47. skilleter_thingy/rmdupe.py +550 -0
  48. skilleter_thingy/rpylint.py +91 -0
  49. skilleter_thingy/run.py +334 -0
  50. skilleter_thingy/s3_sync.py +383 -0
  51. skilleter_thingy/splitpics.py +99 -0
  52. skilleter_thingy/strreplace.py +82 -0
  53. skilleter_thingy/sysmon.py +435 -0
  54. skilleter_thingy/tfm.py +920 -0
  55. skilleter_thingy/tfm_pane.py +595 -0
  56. skilleter_thingy/tfparse.py +101 -0
  57. skilleter_thingy/tidy.py +160 -0
  58. skilleter_thingy/trimpath.py +84 -0
  59. skilleter_thingy/window_rename.py +92 -0
  60. skilleter_thingy/xchmod.py +125 -0
  61. skilleter_thingy/yamlcheck.py +89 -0
  62. skilleter_thingy-0.0.22.dist-info/LICENSE +619 -0
  63. skilleter_thingy-0.0.22.dist-info/METADATA +22 -0
  64. skilleter_thingy-0.0.22.dist-info/RECORD +67 -0
  65. skilleter_thingy-0.0.22.dist-info/WHEEL +5 -0
  66. skilleter_thingy-0.0.22.dist-info/entry_points.txt +43 -0
  67. skilleter_thingy-0.0.22.dist-info/top_level.txt +1 -0
@@ -0,0 +1,180 @@
1
+ #! /usr/bin/env python3
2
+
3
+ ################################################################################
4
+ """ Thingy 'git-br' command - output branch information
5
+
6
+ Author: John Skilleter
7
+
8
+ Licence: GPL v3 or later
9
+
10
+ TODO: Command line options for list of fields to output
11
+ TODO: Command line options for sort order
12
+ TODO: Debate the delete option, which currently isn't implemented
13
+ """
14
+ ################################################################################
15
+
16
+ import sys
17
+ import argparse
18
+ import fnmatch
19
+ import datetime
20
+
21
+ from dateutil.parser import parse
22
+ from dateutil.relativedelta import relativedelta
23
+
24
+ from skilleter_thingy import git
25
+ from skilleter_thingy import colour
26
+
27
+ ################################################################################
28
+
29
+ def parse_command_line():
30
+ """ Parse the command line """
31
+
32
+ parser = argparse.ArgumentParser(description='List or delete branches that have been merged')
33
+
34
+ parser.add_argument('-a', '--all', action='store_true', help='List all branches, including remotes')
35
+ parser.add_argument('-d', '--delete', action='store_true',
36
+ help='Delete the specified branch(es), even if it is the current one (list of branches to delete must be supplied as parameters)')
37
+ parser.add_argument('branches', nargs='*', help='Filter the list of branches according to one or more patterns')
38
+
39
+ args = parser.parse_args()
40
+
41
+ if args.delete and not args.branches:
42
+ colour.error('[RED:ERROR]: You must specify the branches to delete')
43
+
44
+ return args
45
+
46
+ ################################################################################
47
+
48
+ def branch_match(ref, matching_branches):
49
+ """ Return True if ref matches an entry in matching_branches """
50
+
51
+ if matching_branches:
52
+ for branch in matching_branches:
53
+ if '?' in branch or '*' in branch:
54
+ if branch[0] not in ['?', '*']:
55
+ branch = f'*{branch}'
56
+ if branch[-1] not in ['?', '*']:
57
+ branch = f'{branch}*'
58
+
59
+ if fnmatch.fnmatch(ref, branch):
60
+ return True
61
+ elif branch in ref:
62
+ return True
63
+
64
+ return False
65
+
66
+ return True
67
+
68
+ ################################################################################
69
+
70
+ def get_matching_branches(args):
71
+ """ Get a list of branches matching those specified in the script arguments """
72
+
73
+ # Get the SHA1, date, author and name of the tip commit on each branch, including remotes
74
+ # and keep track of the maximum length of each field
75
+
76
+ branches = []
77
+
78
+ for ref in git.ref(sort='-committerdate', fields=('objectname:short', 'committerdate', 'authorname', 'refname:short'), remotes=args.all):
79
+ if branch_match(ref[3], args.branches):
80
+ branches.append(ref)
81
+
82
+ return branches
83
+
84
+ ################################################################################
85
+
86
+ def list_branches(branches):
87
+ """ List branches. """
88
+
89
+ max_len = [0] * len(branches[0])
90
+
91
+ user = git.config_get('user', 'name')
92
+
93
+ # Output the fields in columns, highlighting user's own branches and those owned by Jenkins
94
+ # Replacing references to today and yesterday's dates with 'today' and 'yesterday' and
95
+ # reformatting dates and time for readability.
96
+
97
+ today = datetime.date.today()
98
+ yesterday = today - relativedelta(days=1)
99
+
100
+ all_output = []
101
+
102
+ current_branch = git.branch()
103
+
104
+ for branch in branches:
105
+ output = []
106
+
107
+ for i, field in enumerate(branch):
108
+ if i==1:
109
+ field = parse(field)
110
+ time_str = field.strftime('%H:%M:%S')
111
+
112
+ if field.date() == today:
113
+ field = 'today ' + time_str
114
+ elif field.date() == yesterday:
115
+ field = 'yesterday ' + time_str
116
+ else:
117
+ field = field.date().strftime('%d/%m/%Y') + ' ' + time_str
118
+
119
+ output.append('%-*s' % (max_len[i], field))
120
+ max_len[i] = max(max_len[i], len(field))
121
+
122
+ highlight = 'GREEN' if branch[3] in ('master', 'main', 'develop') \
123
+ else 'BOLD' if branch[3] == current_branch \
124
+ else 'BLUE' if branch[2] == user \
125
+ else 'NORMAL'
126
+
127
+ all_output.append({'highlight': highlight, 'output': output})
128
+
129
+ for output in all_output:
130
+ line = []
131
+ for i, field in enumerate(output['output']):
132
+ line.append('%-*s' % (max_len[i], field))
133
+
134
+ colour.write('[%s:%s]' % (output['highlight'], ' '.join(line).rstrip()))
135
+
136
+ ################################################################################
137
+
138
+ def delete_branches(branches):
139
+ """ Delete matching branches. Report an error if no branches specified """
140
+
141
+ if not branches:
142
+ print('ERROR: The branches to delete must be specified')
143
+ sys.exit(1)
144
+
145
+ print('TODO: Deleting %s' % branches)
146
+
147
+ # TODO: List branches, prompt user, delete each branch - if current branch then checkout develop, main or master first
148
+
149
+ ################################################################################
150
+
151
+ def main():
152
+ """ Main function """
153
+
154
+ args = parse_command_line()
155
+
156
+ branches = get_matching_branches(args)
157
+
158
+ if args.delete:
159
+ delete_branches(branches)
160
+ else:
161
+ list_branches(branches)
162
+
163
+ ################################################################################
164
+
165
+ def git_br():
166
+ """Entry point"""
167
+
168
+ try:
169
+ main()
170
+ except KeyboardInterrupt:
171
+ sys.exit(1)
172
+ except BrokenPipeError:
173
+ sys.exit(2)
174
+ except git.GitError as exc:
175
+ colour.error(f'[RED:ERROR]: {exc.msg}', status=exc.status)
176
+
177
+ ################################################################################
178
+
179
+ if __name__ == '__main__':
180
+ git_br()
@@ -0,0 +1,142 @@
1
+ #! /usr/bin/env python3
2
+
3
+ ################################################################################
4
+ """ Thingy "git-ca" command - an intelligent version of "git commit --amend"
5
+
6
+ Copyright (C) 2017-18 John Skilleter
7
+
8
+ Licence: GPL v3 or later
9
+
10
+ TODO: Handle attempt to amend commit in newly-initialised repo with no commits in.
11
+ TODO: Fix failure with "fatal: pathspec "FILENAME" did not match any files" whilst amending a commit to include a deleted file.
12
+ """
13
+ ################################################################################
14
+
15
+ import os
16
+ import argparse
17
+ import sys
18
+
19
+ from skilleter_thingy import colour
20
+ from skilleter_thingy import git
21
+ from skilleter_thingy import logger
22
+
23
+ ################################################################################
24
+
25
+ def main():
26
+ """ Amend a comment, updating modified files that are already committed and
27
+ adding files that are listed on the command line """
28
+
29
+ # Files to add to git before committing and files to commit
30
+
31
+ files_to_add = []
32
+ files_to_commit = []
33
+
34
+ # Parse the command line
35
+
36
+ parser = argparse.ArgumentParser(
37
+ description='Amend changes to the current commit. Updates files that are already in the commit and, optionally, adds additional files.')
38
+
39
+ parser.add_argument('-A', '--added', action='store_true', help='Update files in the current commit, including files added with "git add"')
40
+ parser.add_argument('-a', '--all', action='store_true', help='Append all locally-modified, tracked files to the current commit')
41
+ parser.add_argument('-e', '--everything', action='store_true', help='Append all modified and untracked files to the current commit (implies --all)')
42
+ parser.add_argument('-i', '--ignored', action='store_true', dest='ignored', help='Include files normally hidden by .gitignore')
43
+ parser.add_argument('-p', '--patch', action='store_true', help='Use the interactive patch selection interface to chose which changes to commit.')
44
+ parser.add_argument('-v', '--verbose', action='store_true', help='Verbose mode')
45
+ parser.add_argument('-D', '--dry-run', action='store_true', help='Dry-run')
46
+
47
+ parser.add_argument('files', nargs='*', help='List of files to add to the commit')
48
+
49
+ args = parser.parse_args()
50
+
51
+ # Configure logger
52
+
53
+ log = logger.init(__name__)
54
+
55
+ if args.verbose:
56
+ log.setLevel(logger.INFO)
57
+ log.info('Debug logging enabled')
58
+
59
+ # 'Add' implies 'all'
60
+
61
+ if args.everything:
62
+ args.all = True
63
+
64
+ # If there are any files on the command line then add them
65
+ # to the list of files to be committed
66
+
67
+ if args.files:
68
+ for filename in args.files:
69
+ rel_path = git.tree_path(filename)
70
+ files_to_add.append(rel_path)
71
+
72
+ # Move to the working tree
73
+
74
+ working_tree = git.working_tree()
75
+
76
+ if not working_tree:
77
+ colour.error('fatal: not a git repository (or any of the parent directories)')
78
+
79
+ os.chdir(working_tree)
80
+
81
+ # Get the list of files modified in the most recent commit
82
+
83
+ current_commit = git.commit_info('HEAD', 'HEAD^')
84
+
85
+ # Get the list of locally-modified and untracked files, including
86
+ # files matching .gitignore, if necessary
87
+
88
+ log.info('Getting list of changed files')
89
+ local_changes = git.status_info(args.ignored)
90
+
91
+ for change in local_changes:
92
+ log.info('Changed: %s (%s)', change, local_changes[change])
93
+
94
+ if change in current_commit or (args.added and local_changes[change][0] == 'A'):
95
+ # Locally changed and already in the commit or, optionally, added to it, so update it
96
+
97
+ files_to_commit.append(change)
98
+
99
+ elif args.all and (local_changes[change][1] in ('M', 'A', 'D', 'T') or local_changes[change][0] == 'D'):
100
+ # Tracked and 'all' option specified so add it to the commit
101
+
102
+ files_to_commit.append(change)
103
+
104
+ elif args.everything and local_changes[change][0] in ('!', '?'):
105
+ # Untracked and 'add' option specified so add it to Git and the commit
106
+
107
+ files_to_add.append(change)
108
+
109
+ if files_to_add:
110
+ try:
111
+ git.add(files_to_add)
112
+ except git.GitError as exc:
113
+ colour.error(exc.msg, status=exc.status)
114
+
115
+ files_to_commit += files_to_add
116
+
117
+ # Perform the commit running in the foreground in case the user is using a console
118
+ # mode text editor for commit comments.
119
+
120
+ log.info('Files to commit: %s', files_to_commit)
121
+
122
+ try:
123
+ git.commit(files_to_commit, amend=True, foreground=True, patch=args.patch, dry_run=args.dry_run)
124
+ except git.GitError as exc:
125
+ sys.exit(exc.status)
126
+
127
+ ################################################################################
128
+
129
+ def git_ca():
130
+ """Entry point"""
131
+
132
+ try:
133
+ main()
134
+ except KeyboardInterrupt:
135
+ sys.exit(1)
136
+ except BrokenPipeError:
137
+ sys.exit(2)
138
+
139
+ ################################################################################
140
+
141
+ if __name__ == '__main__':
142
+ git_ca()
@@ -0,0 +1,287 @@
1
+ #! /usr/bin/env python3
2
+
3
+ ################################################################################
4
+ """ Thingy 'git-cleanup' command - list or delete branches that have been merged.
5
+
6
+ Author: John Skilleter
7
+
8
+ Licence: GPL v3 or later
9
+ """
10
+ ################################################################################
11
+
12
+ import sys
13
+ import argparse
14
+ import logging
15
+
16
+ from skilleter_thingy import git
17
+ from skilleter_thingy import colour
18
+
19
+ ################################################################################
20
+ # Constants
21
+
22
+ # Branches that we will never delete
23
+
24
+ PROTECTED_BRANCHES = ['develop', 'master', 'main', 'release', 'hotfix']
25
+
26
+ ################################################################################
27
+
28
+ def parse_command_line():
29
+ """ Parse the command line, returning the arguments """
30
+
31
+ parser = argparse.ArgumentParser(
32
+ description='List or delete branches that have been merged.\nWhen deleting branches, also delete tracking branches that are not longer on the remote.')
33
+
34
+ parser.add_argument('-d', '--delete', action='store_true', dest='delete', help='Delete all branches that have been merged')
35
+ parser.add_argument('-m', '--master', '--main', dest='master',
36
+ help='Specify the master branch (Attempts to read this from GitLab or defaults to "develop" if present or "master" or "main" otherwise')
37
+ parser.add_argument('-f', '--force', action='store_true', dest='force', help='Allow protected branches (e.g. master) to be removed')
38
+ parser.add_argument('-u', '--unmerged', action='store_true', dest='list_unmerged', help='List branches that have NOT been merged')
39
+ parser.add_argument('-y', '--yes', action='store_true', dest='force', help='Assume "yes" in response to any prompts (e.g. to delete branches)')
40
+ parser.add_argument('--debug', action='store_true', help='Enable debug output')
41
+
42
+ parser.add_argument('branches', nargs='*', help='List of branches to check (default is all branches)')
43
+
44
+ return parser.parse_args()
45
+
46
+ ################################################################################
47
+
48
+ def validate_options(args, all_branches):
49
+ """ Check that the command line options make sense """
50
+
51
+ # If the master branch has not been specified try to get it from GitLab and then default to either 'develop', 'main', or 'master'
52
+
53
+ if not args.master:
54
+ args.master = git.default_branch()
55
+
56
+ if not args.master:
57
+ if 'develop' in all_branches:
58
+ args.master = 'develop'
59
+ elif 'main' in all_branches:
60
+ args.master = 'main'
61
+ elif 'master' in all_branches:
62
+ args.master = 'master'
63
+ else:
64
+ colour.error('You must specify a master branch as the repo contains no obvious master branch')
65
+
66
+ # Check that the master branch actually exists
67
+
68
+ if args.master not in all_branches:
69
+ colour.error('The "%s" branch does not exist in the repo' % args.master)
70
+
71
+ # Check that the user isn't trying to remove a branch that is normally sacrosanct
72
+
73
+ if not args.force and args.branches:
74
+ for branch in all_branches:
75
+ if branch in PROTECTED_BRANCHES:
76
+ colour.error('You must use the "--force" option to delete protected branches (%s)' % ', '.join(PROTECTED_BRANCHES))
77
+
78
+ # If no list of branches to check has been specified, use all the branches
79
+
80
+ if not args.branches:
81
+ args.branches = all_branches
82
+
83
+ ################################################################################
84
+
85
+ def main():
86
+ """ Entry point """
87
+
88
+ # Handle the command line
89
+
90
+ args = parse_command_line()
91
+
92
+ # Enable logging if requested
93
+
94
+ if args.debug:
95
+ logging.basicConfig(level=logging.INFO)
96
+
97
+ # Get the list of all local branches
98
+
99
+ try:
100
+ all_branches = [branch for branch in git.branches()]
101
+ except git.GitError as exc:
102
+ colour.error(exc.msg, status=exc.status)
103
+
104
+ logging.info('Branches=%s', all_branches)
105
+
106
+ # Check that the command line options are sensible, including the list of branches (if any)
107
+
108
+ validate_options(args, all_branches)
109
+
110
+ # Checkout and update the master branch then switch back
111
+
112
+ logging.info('Checking out %s branch', args.master)
113
+
114
+ try:
115
+ git.checkout(args.master)
116
+
117
+ logging.info('Running git pull')
118
+
119
+ git.pull()
120
+
121
+ logging.info('Checking out previous branch')
122
+
123
+ git.checkout('-')
124
+
125
+ except git.GitError as exc:
126
+ colour.error(exc.msg, status=exc.status)
127
+
128
+ # 'reported' is True when we've reported something so we can put a blank line before the
129
+ # next item (if there is one).
130
+
131
+ reported = False
132
+
133
+ # List of branches that we will delete (if we aren't just listing possibilities)
134
+
135
+ logging.info('Determining whether any branches can be deleted (not master branch, not protected and no outstanding commits)')
136
+
137
+ branches_to_delete = []
138
+
139
+ # Iterate through the branches, ignoring protected branches and the current master
140
+
141
+ for branch in args.branches:
142
+ if branch not in PROTECTED_BRANCHES and branch not in args.master:
143
+
144
+ # Has the branch got commits that haven't been merged to the master branch?
145
+
146
+ logging.info('Checking for umerged commits on %s (against %s)', branch, args.master)
147
+
148
+ try:
149
+ unmerged = git.git(['log', '--no-merges', '--oneline', branch, '^%s' % args.master, '--'])
150
+ except git.GitError as exc:
151
+ sys.stderr.write('%s\n' % exc.msg)
152
+ sys.exit(exc.status)
153
+
154
+ # Either mark merged branches to be deleted or list unmerged or merged ones
155
+
156
+ if args.delete:
157
+ # Mark the branch as deleteable if the branch doesn't have unmerged commits
158
+ # and it either isn't protected or we're forcing
159
+
160
+ if not unmerged and (args.force or branch not in PROTECTED_BRANCHES):
161
+ logging.info('Branch %s can be deleted', branch)
162
+
163
+ branches_to_delete.append(branch)
164
+
165
+ elif args.list_unmerged:
166
+ if unmerged:
167
+ # if the branch has commits that are not on the master branch then list it as unmerged
168
+
169
+ if reported:
170
+ print()
171
+ else:
172
+ colour.write('Branches that have not been merged to [BLUE:%s]:' % args.master)
173
+
174
+ colour.write(' [BLUE:%s]: [BOLD:%d] unmerged commits' % (branch, len(unmerged)))
175
+
176
+ for commit in unmerged:
177
+ print(' %s' % commit)
178
+
179
+ reported = True
180
+
181
+ elif not unmerged:
182
+ # If the branch hasn't got unique commits then it has been merged (or is empty)
183
+
184
+ if not reported:
185
+ colour.write('Branches that have %sbeen merged to [BLUE:%s]' % ('not ' if args.list_unmerged else '', args.master))
186
+
187
+ colour.write(' [BLUE:%s]' % branch)
188
+
189
+ reported = True
190
+
191
+ # If we have branches to delete then delete them
192
+
193
+ if args.delete:
194
+ if branches_to_delete:
195
+
196
+ logging.info('Deleting branch(es): %s', branches_to_delete)
197
+
198
+ if not args.force:
199
+ colour.write('The following branches have already been merged to the [BLUE:%s] branch and can be deleted:' % args.master)
200
+ for branch in branches_to_delete:
201
+ colour.write(' [BLUE:%s]' % branch)
202
+
203
+ print()
204
+ confirm = input('Are you sure that you want to delete these branches? ')
205
+
206
+ if confirm.lower() not in ('y', 'yes'):
207
+ colour.error('**aborted**')
208
+
209
+ print()
210
+
211
+ # Delete the branches, switching to the master branch before attempting to delete the current one
212
+
213
+ for branch in branches_to_delete:
214
+ if branch == git.branch():
215
+ colour.write('Switching to [BLUE:%s] branch before deleting current branch.' % args.master)
216
+ git.checkout(args.master)
217
+
218
+ try:
219
+ logging.info('Deleting %s', branch)
220
+
221
+ git.delete_branch(branch, force=True)
222
+ except git.GitError as exc:
223
+ colour.error(str(exc), status=exc.status)
224
+
225
+ colour.write('Deleted [BLUE:%s]' % branch)
226
+ else:
227
+ colour.write('There are no branches that have been merged to the [BLUE:%s] branch.' % args.master)
228
+
229
+ # Finally run remote pruning (note that we don't have an option to
230
+ # list branches that *can't* be pruned (yet))
231
+
232
+ reported = False
233
+ prunable = False
234
+
235
+ # Look for prunable branches and report them
236
+
237
+ logging.info('Looking for remote tracking branches that can be pruned')
238
+
239
+ for remote in git.remotes():
240
+ for prune in git.remote_prune(remote, dry_run=True):
241
+ if not reported:
242
+ print()
243
+ if args.force:
244
+ print('Deleting remote tracking branches:')
245
+ else:
246
+ print('Remote tracking branches that can be deleted:')
247
+ reported = True
248
+
249
+ colour.write(' [BLUE:%s]' % prune)
250
+ prunable = True
251
+
252
+ # If we are deleting things and have things to delete then delete things
253
+
254
+ if args.delete and prunable:
255
+ if not args.force:
256
+ print()
257
+ confirm = input('Are you sure that you want to prune these branches? ')
258
+
259
+ if confirm.lower() not in ('y', 'yes'):
260
+ colour.error('**aborted**')
261
+
262
+ print()
263
+
264
+ for remote in git.remotes():
265
+ logging.info('Pruning remote branches from %s', remote)
266
+
267
+ pruned = git.remote_prune(remote)
268
+
269
+ for branch in pruned:
270
+ colour.write('Deleted [BLUE:%s]' % branch)
271
+
272
+ ################################################################################
273
+
274
+ def git_cleanup():
275
+ """Entry point"""
276
+
277
+ try:
278
+ main()
279
+ except KeyboardInterrupt:
280
+ sys.exit(1)
281
+ except BrokenPipeError:
282
+ sys.exit(2)
283
+
284
+ ################################################################################
285
+
286
+ if __name__ == '__main__':
287
+ git_cleanup()