skilleter-thingy 0.3.14__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.
Files changed (39) hide show
  1. skilleter_thingy/__init__.py +0 -0
  2. skilleter_thingy/addpath.py +107 -0
  3. skilleter_thingy/console_colours.py +63 -0
  4. skilleter_thingy/ffind.py +535 -0
  5. skilleter_thingy/ggit.py +88 -0
  6. skilleter_thingy/ggrep.py +155 -0
  7. skilleter_thingy/git_br.py +186 -0
  8. skilleter_thingy/git_ca.py +147 -0
  9. skilleter_thingy/git_cleanup.py +297 -0
  10. skilleter_thingy/git_co.py +227 -0
  11. skilleter_thingy/git_common.py +68 -0
  12. skilleter_thingy/git_hold.py +162 -0
  13. skilleter_thingy/git_parent.py +84 -0
  14. skilleter_thingy/git_retag.py +67 -0
  15. skilleter_thingy/git_review.py +1450 -0
  16. skilleter_thingy/git_update.py +398 -0
  17. skilleter_thingy/git_wt.py +72 -0
  18. skilleter_thingy/gitcmp_helper.py +328 -0
  19. skilleter_thingy/gitprompt.py +293 -0
  20. skilleter_thingy/linecount.py +154 -0
  21. skilleter_thingy/multigit.py +915 -0
  22. skilleter_thingy/py_audit.py +133 -0
  23. skilleter_thingy/remdir.py +127 -0
  24. skilleter_thingy/rpylint.py +98 -0
  25. skilleter_thingy/strreplace.py +82 -0
  26. skilleter_thingy/test.py +34 -0
  27. skilleter_thingy/tfm.py +948 -0
  28. skilleter_thingy/tfparse.py +101 -0
  29. skilleter_thingy/trimpath.py +82 -0
  30. skilleter_thingy/venv_create.py +47 -0
  31. skilleter_thingy/venv_template.py +47 -0
  32. skilleter_thingy/xchmod.py +124 -0
  33. skilleter_thingy/yamlcheck.py +89 -0
  34. skilleter_thingy-0.3.14.dist-info/METADATA +606 -0
  35. skilleter_thingy-0.3.14.dist-info/RECORD +39 -0
  36. skilleter_thingy-0.3.14.dist-info/WHEEL +5 -0
  37. skilleter_thingy-0.3.14.dist-info/entry_points.txt +31 -0
  38. skilleter_thingy-0.3.14.dist-info/licenses/LICENSE +619 -0
  39. skilleter_thingy-0.3.14.dist-info/top_level.txt +1 -0
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env python3
2
+ """Archive one or more branches by tagging the branch then deleting it
3
+ The branch tag is 'archive/BRANCH_NAME'"""
4
+
5
+ import os
6
+ import sys
7
+ import argparse
8
+ import fnmatch
9
+
10
+ from skilleter_modules import colour
11
+ from skilleter_modules import git
12
+
13
+ ################################################################################
14
+ # Prefix for tags representing archived branches
15
+
16
+ ARCHIVE_PREFIX = 'archive/'
17
+
18
+ ################################################################################
19
+
20
+ def archive_tag_name(branch):
21
+ """Return the tag name for an archive branch"""
22
+
23
+ return f'{ARCHIVE_PREFIX}{branch}'
24
+
25
+ ################################################################################
26
+
27
+ def archive_branch_name(tag):
28
+ """Return the branch name for an archive tag"""
29
+
30
+ if not tag.startswith(ARCHIVE_PREFIX):
31
+ raise git.GitError(f'{tag} is not an archive tag')
32
+
33
+ return tag[len(ARCHIVE_PREFIX):]
34
+
35
+ ################################################################################
36
+
37
+ def archive_tags():
38
+ """Return the list of current archive tags"""
39
+
40
+ return [tag for tag in git.tags() if tag.startswith(ARCHIVE_PREFIX)]
41
+
42
+ ################################################################################
43
+
44
+ def archive_branches(branches):
45
+ """Archive one or more branches"""
46
+
47
+ tags = archive_tags()
48
+ current_branch = git.branch()
49
+
50
+ for branch in branches:
51
+ if not git.isbranch(branch):
52
+ colour.error(f'Branch {branch} does not exist', prefix=True)
53
+
54
+ if archive_tag_name(branch) in tags:
55
+ colour.error(f'An archive tag already exists for branch {branch}', prefix=True)
56
+
57
+ if branch == current_branch:
58
+ colour.error('Cannot archive the current branch', prefix=True)
59
+
60
+ for branch in branches:
61
+ tag_name = archive_tag_name(branch)
62
+
63
+ git.tag_apply(tag_name, branch)
64
+ git.delete_branch(branch, force=True)
65
+
66
+ for remote in git.remotes():
67
+ git.push(repository=remote, tags=True)
68
+
69
+ ################################################################################
70
+
71
+ def list_archive_branches(branches):
72
+ """List archive branches, optionally only those matching entries in the
73
+ branches parameter"""
74
+
75
+ tags = archive_tags()
76
+
77
+ if branches:
78
+ report = set()
79
+
80
+ for branch in branches:
81
+ for tag in tags:
82
+ branch_name = archive_branch_name(tag)
83
+ if branch_name not in report and fnmatch.fnmatch(branch_name, branch):
84
+ report.add(branch_name)
85
+ else:
86
+ report = set(tags)
87
+
88
+ for branch_name in sorted(report):
89
+ print(branch_name)
90
+
91
+ ################################################################################
92
+
93
+ def restore_archive_branches(branches):
94
+ """Restore archived branches"""
95
+
96
+ tags = archive_tags()
97
+
98
+ for branch in branches:
99
+ if archive_tag_name(branch) not in tags:
100
+ colour.error(f'Archive branch {branch} does not exist', prefix=True)
101
+
102
+ archive_tag_names = []
103
+
104
+ for branch in branches:
105
+ archive_tag = archive_tag_name(branch)
106
+ archive_tag_names.append(archive_tag)
107
+
108
+ git.checkout(branch, commit=archive_tag)
109
+ git.tag_delete(archive_tag)
110
+
111
+ for remote in git.remotes():
112
+ git.push(repository=remote, delete=True, refspec=archive_tag_names)
113
+
114
+ ################################################################################
115
+
116
+ def main():
117
+ """Main function"""
118
+
119
+ parser = argparse.ArgumentParser(description='Archive, list or recover one or more Git branches')
120
+ parser.add_argument('--list', '-l', action='store_true', help='List archived branches')
121
+ parser.add_argument('--restore', '-r', action='store_true', help='Restore archived branches')
122
+ parser.add_argument('--path', '-C', nargs=1, type=str, default=None,
123
+ help='Run the command in the specified directory')
124
+ parser.add_argument('branches', nargs='*', help='Branches')
125
+
126
+ args = parser.parse_args()
127
+
128
+ if args.list and args.restore:
129
+ colour.error('The list and restore options cannot be specified together', prefix=True)
130
+
131
+ if not args.branches and not args.list:
132
+ colour.error('No branches specified', prefix=True)
133
+
134
+ if args.path:
135
+ os.chdir(args.path[0])
136
+
137
+ if args.list:
138
+ list_archive_branches(args.branches)
139
+ elif args.restore:
140
+ restore_archive_branches(args.branches)
141
+ else:
142
+ archive_branches(args.branches)
143
+
144
+ ################################################################################
145
+
146
+ def git_hold():
147
+ """Entry point"""
148
+
149
+ try:
150
+ main()
151
+
152
+ except KeyboardInterrupt:
153
+ sys.exit(1)
154
+ except BrokenPipeError:
155
+ sys.exit(2)
156
+ except git.GitError as exc:
157
+ colour.error(exc.msg, status=exc.status, prefix=True)
158
+
159
+ ################################################################################
160
+
161
+ if __name__ == '__main__':
162
+ git_hold()
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Attempt to determine the parent branch of a commit by tracking down
5
+ the branch commit history and looking for other branches that share
6
+ the same commit. Can optionally ignore feature branches and/or report
7
+ the distance to the potential parent.
8
+ """
9
+
10
+ import os
11
+ import argparse
12
+ import sys
13
+
14
+ from skilleter_modules import git
15
+ from skilleter_modules import colour
16
+
17
+ ################################################################################
18
+
19
+ def main():
20
+ """ Main function """
21
+
22
+ current_branch = git.branch()
23
+
24
+ parser = argparse.ArgumentParser(description='Attempt to determine the parent branch for the specified branch (defaulting to the current one)')
25
+ parser.add_argument('--all', '-a', action='store_true', help='Include feature branches as possible parents')
26
+ parser.add_argument('--verbose', '-v', action='store_true', help='Report verbose results (includes number of commits between branch and parent)')
27
+ parser.add_argument('--path', '-C', nargs=1, type=str, default=None,
28
+ help='Run the command in the specified directory')
29
+ parser.add_argument('branch', action='store', nargs='?', type=str, default=current_branch,
30
+ help=f'Branch, commit or commit (defaults to current branch; {current_branch})')
31
+
32
+ args = parser.parse_args()
33
+
34
+ if args.path:
35
+ os.chdir(args.path[0])
36
+
37
+ if args.all:
38
+ any_parents, any_distance = git.parents(args.branch)
39
+ else:
40
+ any_parents = []
41
+
42
+ parents, distance = git.parents(args.branch, ignore='feature/*')
43
+
44
+ # If we have feature and non-feature branch candidates, decide which to report
45
+ # (one or both) based on distance.
46
+
47
+ if parents and any_parents:
48
+ if any_distance < distance:
49
+ parents = any_parents
50
+ distance = any_distance
51
+ elif any_distance == distance:
52
+ for more in any_parents:
53
+ if more not in parents:
54
+ parents.append(more)
55
+
56
+ if parents:
57
+ if args.verbose:
58
+ if len(parents) == 1:
59
+ colour.write(f'Parent branch [BLUE:{parents[0]}] is [BLUE:{distance}] commits away from [BLUE:{args.branch}]')
60
+ else:
61
+ colour.write(f'Parent branches [BLUE:%s] are [BLUE:{distance}] commits away from [BLUE:{args.branch}]' % (', '.join(parents)))
62
+ else:
63
+ print(', '.join(parents))
64
+ else:
65
+ colour.error('Could not determine parent branch\n', prefix=True)
66
+
67
+ ################################################################################
68
+
69
+ def git_parent():
70
+ """Entry point"""
71
+
72
+ try:
73
+ main()
74
+ except KeyboardInterrupt:
75
+ sys.exit(1)
76
+ except BrokenPipeError:
77
+ sys.exit(2)
78
+ except git.GitError as exc:
79
+ colour.error(exc.msg, status=exc.status, prefix=True)
80
+
81
+ ################################################################################
82
+
83
+ if __name__ == '__main__':
84
+ git_parent()
@@ -0,0 +1,67 @@
1
+ #! /usr/bin/env python3
2
+
3
+ ################################################################################
4
+ """ Apply or update a tag, optionally updating it on the remote as well.
5
+
6
+ Copyright (C) 2025 John Skilleter
7
+
8
+ Licence: GPL v3 or later
9
+ """
10
+ ################################################################################
11
+
12
+ import os
13
+ import sys
14
+ import argparse
15
+
16
+ from skilleter_modules import git
17
+ from skilleter_modules import colour
18
+
19
+ ################################################################################
20
+
21
+ def main():
22
+ """ Main function """
23
+
24
+ # Command line parameters
25
+
26
+ parser = argparse.ArgumentParser(description='Apply or update a tag, optionally updating it on the remote as well.')
27
+ parser.add_argument('--push', '-p', action='store_true', help='Push the tag to the remote')
28
+ parser.add_argument('--path', '-C', nargs=1, type=str, default=None,
29
+ help='Run the command in the specified directory')
30
+ parser.add_argument('tag', nargs=1, help='The tag')
31
+
32
+ args = parser.parse_args()
33
+
34
+ # Change directory, if specified
35
+
36
+ if args.path:
37
+ os.chdir(args.path[0])
38
+
39
+ tag = args.tag[0]
40
+
41
+ # Delete the tag if it currently exists, optionally pushing the deletion
42
+
43
+ if tag in git.tags():
44
+ git.tag_delete(tag, push=args.push)
45
+
46
+ # Apply the tag
47
+
48
+ git.tag_apply(tag, 'HEAD', push=args.push)
49
+
50
+ ################################################################################
51
+
52
+ def git_retag():
53
+ """Entry point"""
54
+
55
+ try:
56
+ main()
57
+ except KeyboardInterrupt:
58
+ sys.exit(1)
59
+ except BrokenPipeError:
60
+ sys.exit(2)
61
+ except git.GitError as exc:
62
+ colour.error(exc.msg, status=exc.status, prefix=True)
63
+
64
+ ################################################################################
65
+
66
+ if __name__ == '__main__':
67
+ git_retag()