git-project-core-plugins 0.0.20__tar.gz → 0.0.22__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.
Files changed (65) hide show
  1. git_project_core_plugins-0.0.22/.git +1 -0
  2. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/PKG-INFO +3 -3
  3. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/_version.py +2 -2
  4. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/__init__.py +27 -0
  5. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/branch.py +222 -0
  6. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/clone.py +98 -0
  7. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/common.py +22 -0
  8. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/config.py +169 -0
  9. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/help.py +298 -0
  10. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/init.py +74 -0
  11. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/run.py +399 -0
  12. git_project_core_plugins-0.0.22/build/lib/git_project_core_plugins/worktree.py +643 -0
  13. git_project_core_plugins-0.0.22/docs/README-template.rst +104 -0
  14. git_project_core_plugins-0.0.22/gen-readme.py +55 -0
  15. git_project_core_plugins-0.0.22/gen-readme.py~ +2 -0
  16. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/PKG-INFO +493 -0
  17. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/SOURCES.txt +21 -0
  18. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/dependency_links.txt +1 -0
  19. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/entry_points.txt +9 -0
  20. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/not-zip-safe +1 -0
  21. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/requires.txt +3 -0
  22. git_project_core_plugins-0.0.22/git_project_core_plugins.egg-info/top_level.txt +1 -0
  23. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/pyproject.toml +1 -1
  24. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/requirements.txt +1 -1
  25. git_project_core_plugins-0.0.22/src/git_project_core_plugins/artifact.py +323 -0
  26. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/branch.py +3 -0
  27. git_project_core_plugins-0.0.22/src/git_project_core_plugins/worktree.py +684 -0
  28. git_project_core_plugins-0.0.20/src/git_project_core_plugins/worktree.py → git_project_core_plugins-0.0.22/src/git_project_core_plugins/worktree.py~ +1 -1
  29. git_project_core_plugins-0.0.22/test.out +38 -0
  30. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_artifact.py +1 -1
  31. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_branch.py +4 -0
  32. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_run.py +16 -16
  33. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_worktree.py +27 -9
  34. git_project_core_plugins-0.0.20/.git +0 -1
  35. git_project_core_plugins-0.0.20/docs/authors.rst~ +0 -36
  36. git_project_core_plugins-0.0.20/docs/changelog.rst~ +0 -39
  37. git_project_core_plugins-0.0.20/docs/conf.py~ +0 -57
  38. git_project_core_plugins-0.0.20/docs/index.rst~ +0 -46
  39. git_project_core_plugins-0.0.20/docs/intro.rst~ +0 -29
  40. git_project_core_plugins-0.0.20/pyproject.toml~ +0 -260
  41. git_project_core_plugins-0.0.20/requirements.txt~ +0 -22
  42. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/COPYING +0 -0
  43. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/MANIFEST.in +0 -0
  44. {git_project_core_plugins-0.0.20/src → git_project_core_plugins-0.0.22/build/lib}/git_project_core_plugins/artifact.py +0 -0
  45. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/Makefile +0 -0
  46. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/authors.rst +0 -0
  47. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/changelog.rst +0 -0
  48. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/conf.py +0 -0
  49. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/index.rst +0 -0
  50. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/intro.rst +0 -0
  51. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/license.rst +0 -0
  52. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/docs/make.bat +0 -0
  53. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/__init__.py +0 -0
  54. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/clone.py +0 -0
  55. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/common.py +0 -0
  56. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/config.py +0 -0
  57. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/help.py +0 -0
  58. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/init.py +0 -0
  59. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/src/git_project_core_plugins/run.py +0 -0
  60. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/common.py +0 -0
  61. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/conftest.py +0 -0
  62. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_clone.py +0 -0
  63. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_config.py +0 -0
  64. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_help.py +0 -0
  65. {git_project_core_plugins-0.0.20 → git_project_core_plugins-0.0.22}/tests/test_init.py +0 -0
@@ -0,0 +1 @@
1
+ gitdir: /Users/dag/projects/git-project-core-plugins/.git/worktrees/master/
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: git-project-core-plugins
3
- Version: 0.0.20
3
+ Version: 0.0.22
4
4
  Summary: The extensible stupid project manager - core functionality
5
5
  Author-email: "David A. Greene" <dag@obbligato.org>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -13,7 +13,7 @@ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or l
13
13
  Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Topic :: Software Development :: Version Control :: Git
15
15
  Requires-Python: >=3
16
- Requires-Dist: git-project>=0.0.24
16
+ Requires-Dist: git-project>=0.0.27
17
17
  Requires-Dist: progressbar
18
18
  Provides-Extra: test
19
19
  Requires-Dist: git-project; extra == 'test'
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.0.20'
16
- __version_tuple__ = version_tuple = (0, 0, 20)
15
+ __version__ = version = '0.0.22'
16
+ __version_tuple__ = version_tuple = (0, 0, 22)
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright 2020 David A. Greene
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
+ # details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along with
16
+ # this program. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ from .artifact import Artifact, ArtifactPlugin
20
+ from .branch import BranchPlugin
21
+ from .run import RunPlugin
22
+ from .clone import ClonePlugin
23
+ from .common import add_plugin_version_argument
24
+ from .config import ConfigPlugin
25
+ from .help import Help, HelpPlugin
26
+ from .init import InitPlugin
27
+ from .worktree import Worktree, WorktreePlugin
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright 2020 David A. Greene
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
+ # details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along with
16
+ # this program. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ """A plugin to add a 'branch' command to git-project. The branch command allows
20
+ query of branch status with respect to the project and pruning of 'finished'
21
+ branches.
22
+
23
+ Summary:
24
+
25
+ git-project branch status [<pattern>]
26
+ git-project branch prune [--no-ask] [<pattern>]
27
+
28
+ """
29
+ from git_project import Git, RunnableConfigObject, Plugin
30
+ from git_project import add_top_level_command, Project, GitProjectException
31
+
32
+ from git_project_core_plugins.common import add_plugin_version_argument
33
+
34
+ import getpass
35
+
36
+ def query_yes_no(question, default="yes"):
37
+ """Ask a yes/no question via input() and return their answer.
38
+
39
+ "question" is a string that is presented to the user.
40
+ "default" is the presumed answer if the user just hits <Enter>.
41
+ It must be "yes" (the default), "no" or None (meaning
42
+ an answer is required of the user).
43
+
44
+ The "answer" return value is True for "yes" or False for "no".
45
+ """
46
+ valid = {"yes": True, "y": True, "ye": True,
47
+ "no": False, "n": False}
48
+ if default is None:
49
+ prompt = " [y/n] "
50
+ elif default == "yes":
51
+ prompt = " [Y/n] "
52
+ elif default == "no":
53
+ prompt = " [y/N] "
54
+ else:
55
+ raise ValueError("invalid default answer: '%s'" % default)
56
+
57
+ while True:
58
+ sys.stdout.write(question + prompt)
59
+ choice = input().lower()
60
+ if default is not None and choice == '':
61
+ return valid[default]
62
+ elif choice in valid:
63
+ return valid[choice]
64
+ else:
65
+ sys.stdout.write("Please respond with 'yes' or 'no' "
66
+ "(or 'y' or 'n').\n")
67
+
68
+ def command_branch_status(git, gitproject, project, clargs):
69
+ """Implement git-project branch status."""
70
+ ref = clargs.name_or_ref
71
+
72
+ if not ref:
73
+ if clargs.all_user:
74
+ ref = 'refs/heads/user/' + getpass.getuser()
75
+ elif clargs.all:
76
+ ref = 'refs/heads'
77
+ else:
78
+ raise GitProjectException('merged requires branch name, pattern, --all-user or --all')
79
+ else:
80
+ if not ref.startswith('refs/'):
81
+ ref = 'refs/heads/' + ref
82
+
83
+ target = clargs.target if clargs.target else None
84
+
85
+ branch_width = 45
86
+ status_width = 8
87
+ separator_width = branch_width + 2 * status_width - (status_width - len('merged'))
88
+
89
+ print('-' * separator_width)
90
+ print('{:<{branch_width}s}{:<{status_width}s}{:<{status_width}s}'.
91
+ format('branch', 'merged', 'pushed',
92
+ branch_width=branch_width, status_width=status_width))
93
+ print('-' * separator_width)
94
+
95
+ for branch in git.iterrefnames([ref]):
96
+ merge_status = 'no'
97
+ if target:
98
+ merge_status = 'yes' if git.branch_is_merged(branch, target) else 'no'
99
+ else:
100
+ merge_status = 'yes' if project.branch_is_merged(branch) else 'no'
101
+
102
+ push_status = 'yes' if project.branch_is_pushed(branch) else 'no'
103
+
104
+ print('{:<{branch_width}s}{:<{status_width}s}{:<{status_width}s}'.
105
+ format(branch[:branch_width-2], merge_status, push_status,
106
+ branch_width=branch_width, status_width=status_width))
107
+ print('-' * separator_width)
108
+
109
+ def command_branch_prune(git, gitproject, project, clargs):
110
+ """Implement git-project branch prune."""
111
+ ref = clargs.name_or_ref
112
+ if not ref:
113
+ if clargs.all_user:
114
+ ref = 'refs/heads/user/' + getpass.getuser()
115
+ else:
116
+ raise GitProjectException('Prune requires branch name, pattern or --all-user')
117
+ else:
118
+ ref = Git.branch_name_to_refname(ref)
119
+
120
+ branch_width = 45
121
+ status_width = 15
122
+ separator_width = branch_width + 2 * status_width
123
+
124
+ print('-' * separator_width)
125
+ print('{:<{branch_width}s}{:<{status_width}s}{:<{status_width}s}'.
126
+ format('branch', 'local status', 'remote status',
127
+ branch_width=branch_width, status_width=status_width))
128
+ print('-' * separator_width)
129
+
130
+ for branch in git.iterrefnames([ref]):
131
+ status = 'merged' if project.branch_is_merged(branch) else 'unmerged'
132
+
133
+ print('{:<{branch_width}s}{:<{status_width}s}'.
134
+ format(branch[:branch_width-2], status,
135
+ branch_width=branch_width, status_width=status_width))
136
+ if clargs.force or status == 'merged':
137
+ if clargs.no_ask or query_yes_no('Prune?', default=None):
138
+ project.prune_branch(branch)
139
+
140
+ class BranchPlugin(Plugin):
141
+ """
142
+ The branch command queries the status of branches against known project
143
+ branches and provides methods to prune old branches.
144
+
145
+ Summary:
146
+
147
+ git <project> branch status [--all] [<refish>]
148
+ git <project> branch prune [--force] [--no-ask]
149
+
150
+ The branch status command checks the given <refish> (or all local branches
151
+ with the --all option) against the project-configured branches. The command
152
+ outputs a table of branches and whether they are merged to a project branch
153
+ and/or pushed to a remote. For example:
154
+
155
+ git <project> config --add branch release
156
+ git <project> branch status mybranch
157
+
158
+ The report will show whether mybranch is merged to the release or master
159
+ branches (master is always a configured project branch) and whether the
160
+ commit pointed to mybranch is pushed to a remote.
161
+
162
+ The branch prune command computes the same information and if the branch is
163
+ merged to a project branch and that project branch is pushed to a remote,
164
+ will ask whether mybranch should be deleted. If the user indicates yes,
165
+ both the local mybranch and its remote counterpart, if any, will be deleted.
166
+
167
+ With --force, branches will be pruneed regardless of merge/push status.
168
+ With --no-ask branch prune operates in batch mode, assuming all merged and
169
+ pushed branches should be pruned.
170
+
171
+ See also:
172
+
173
+ config
174
+
175
+ """
176
+ def __init__(self):
177
+ super().__init__('branch')
178
+
179
+ def add_arguments(self,
180
+ git,
181
+ gitproject,
182
+ project,
183
+ parser_manager,
184
+ plugin_manager):
185
+ """Add arguments for 'git project branch.'"""
186
+ # branch
187
+ branch_parser = add_top_level_command(parser_manager,
188
+ 'branch',
189
+ 'branch',
190
+ help='Manipulate branches')
191
+
192
+ add_plugin_version_argument(branch_parser)
193
+
194
+ branch_subparser = parser_manager.add_subparser(branch_parser,
195
+ 'branch_command',
196
+ help='branch commands')
197
+
198
+ # branch status
199
+ branch_status_parser = parser_manager.add_parser(branch_subparser,
200
+ 'status',
201
+ 'branch-status',
202
+ help='Show branch status')
203
+
204
+ branch_status_parser.set_defaults(func=command_branch_status)
205
+
206
+ branch_status_parser.add_argument('name_or_ref', nargs='?', help='Branch or pattern to filter branches')
207
+ branch_status_parser.add_argument('target', nargs='?', help='Target branch to check against')
208
+ branch_status_parser.add_argument('--all', action='store_true', help='Show all branches')
209
+ branch_status_parser.add_argument('--all-user', action='store_true', help='Show all user\'s branches')
210
+
211
+ # branch prune
212
+ branch_prune_parser = parser_manager.add_parser(branch_subparser,
213
+ 'prune',
214
+ 'branch-prune',
215
+ help='Delete merged branches')
216
+
217
+ branch_prune_parser.set_defaults(func=command_branch_prune)
218
+
219
+ branch_prune_parser.add_argument('name_or_ref', nargs='?', help='Branch name or pattern to filter branches')
220
+ branch_prune_parser.add_argument('--all-user', action='store_true', help='Prune all user\'s branches')
221
+ branch_prune_parser.add_argument('--force', action='store_true', help='Prune even if unmerged')
222
+ branch_prune_parser.add_argument('--no-ask', action='store_true', help='Do not ask before pruning')
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright 2020 David A. Greene
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
+ # details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along with
16
+ # this program. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ """A plugin to add a 'clone' command to git-project. The clone command clones a
20
+ repository and optionally initializes a master worktree environment.
21
+
22
+ Summary:
23
+
24
+ git-project clone <url> [path] [--bare] [--no-master-worktree]
25
+
26
+ """
27
+
28
+ from git_project import add_top_level_command, Plugin
29
+
30
+ from git_project_core_plugins.common import add_plugin_version_argument
31
+
32
+ import getpass
33
+ import os
34
+ from pathlib import Path
35
+ import pygit2
36
+
37
+ def command_clone(git, gitproject, project, clargs):
38
+ """Implement git-project clone"""
39
+ gitdir = git.clone(clargs.url,
40
+ path=clargs.path if hasattr(clargs, 'path') else None,
41
+ bare=clargs.bare)
42
+
43
+ # Now that we have a repository, add sensible project defaults. We know
44
+ # there is no existing project in the config file since we just cloned.
45
+ # This will have the effect of adding a project section.
46
+ project.set_defaults()
47
+
48
+ return gitdir
49
+
50
+ class ClonePlugin(Plugin):
51
+ """
52
+ The clone command clones a repository.
53
+
54
+ Summary:
55
+
56
+ git <project> clone <url> [<path>] [--bare]
57
+
58
+ By itself clone has just the very basic funcionality of the built-in git
59
+ clone command. Plugins may add options to give the clone command more
60
+ features. For example, the woktree command adds a --worktree option to have
61
+ clone create a ``worktree layout.''
62
+
63
+ See also:
64
+
65
+ worktree
66
+
67
+ """
68
+
69
+ def __init__(self):
70
+ super().__init__('clone')
71
+
72
+ def add_arguments(self,
73
+ git,
74
+ gitproject,
75
+ project,
76
+ parser_manager,
77
+ plugin_manager):
78
+ """Add arguments for 'git-project clone.'"""
79
+ # clone
80
+ clone_parser = add_top_level_command(parser_manager,
81
+ 'clone',
82
+ 'clone',
83
+ help='Clone project')
84
+
85
+ add_plugin_version_argument(clone_parser)
86
+
87
+ clone_parser.set_defaults(func=command_clone)
88
+
89
+ clone_parser.add_argument('url',
90
+ help='URL to clone')
91
+
92
+ clone_parser.add_argument('path',
93
+ nargs='?',
94
+ help='Local repository location')
95
+
96
+ clone_parser.add_argument('--bare',
97
+ action='store_true',
98
+ help='Clone a bare repository')
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright 2020 David A. Greene
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
+ # details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along with
16
+ # this program. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ from git_project.commandline import add_version_argument
20
+
21
+ def add_plugin_version_argument(parser):
22
+ add_version_argument(parser, 'git-project-core-plugins')
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # Copyright 2020 David A. Greene
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it under
6
+ # the terms of the GNU General Public License as published by the Free Software
7
+ # Foundation, either version 3 of the License, or (at your option) any later
8
+ # version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
+ # details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along with
16
+ # this program. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ """A plugin to add a 'config' command to git-project. The config command sets
20
+ project-wide git configuration values and prints their values to stdout.
21
+
22
+ Summary:
23
+
24
+ git-project config <key> [--unset] [<value>]
25
+
26
+ """
27
+
28
+ from git_project import ConfigObject, RunnableConfigObject
29
+ from git_project import Plugin, Project, GitProjectException
30
+
31
+ from git_project_core_plugins.common import add_plugin_version_argument
32
+
33
+ def command_config(git, gitproject, project, clargs):
34
+ """Implement git-project config."""
35
+ getter = clargs.getter
36
+ exister = clargs.exister
37
+ classname = clargs.classname
38
+
39
+ subsection = None
40
+ if hasattr(clargs, 'subsection'):
41
+ subsection = clargs.subsection
42
+
43
+ ident = None
44
+ if hasattr(clargs, 'ident'):
45
+ ident = clargs.ident
46
+
47
+ if not exister(git, project.get_section(), subsection, ident):
48
+ if ident:
49
+ raise GitProjectException(f'{classname} \'{ident}\' does not exist')
50
+ else:
51
+ raise GitProjectException(f'No {classname} configured')
52
+
53
+ configitem = getter(git, project, ident) if ident else getter(git, project.get_section())
54
+
55
+ if clargs.value:
56
+ if clargs.unset:
57
+ configitem.rm_item(clargs.name, clargs.value)
58
+ else:
59
+ if clargs.add:
60
+ configitem.add_item(clargs.name, clargs.value)
61
+ else:
62
+ setattr(configitem, clargs.name, clargs.value)
63
+ elif clargs.unset:
64
+ delattr(configitem, clargs.name)
65
+ else:
66
+ value = getattr(configitem, clargs.name)
67
+ print(value)
68
+
69
+ class ConfigPlugin(Plugin):
70
+ """
71
+ The config command manages git config settings under the <project> section.
72
+
73
+ Summary:
74
+
75
+ git <project> config [--add] [--unset] <name> [<value>]
76
+
77
+ The config command operates much like git's built-in config command, except
78
+ all configuration keys are prefixed with <project>, keeping values under a
79
+ single project namespace. This is a convenient way to store parameters for
80
+ other commands. For example:
81
+
82
+ git <project> config builddir /path/to/build
83
+ git <project> add run build "make BUILDDIR={builddir} all"
84
+
85
+ Configuration kays may have their values substituted into other
86
+ configuration values via the {key} specifier. Special commands like build
87
+ perform the substitution recursively, so configuration vaalues may contain
88
+ substitutions of other configuration values which themselves contain
89
+ substitutions, and so on. Importantly, substitution only happens when
90
+ commands are run. Commands should document whether or not they perform
91
+ substitutions.
92
+
93
+ A git config ``sub-section'' may be substituted with its identifier. For
94
+ example:
95
+
96
+ git <project> worktree add myworktree
97
+ git <project> config builddir /path/to/{worktree}/build
98
+
99
+ Here, myworktree is the identifier of a specific worktree sub-section. If
100
+ myworktree is the currently active worktree (that is, the current directory
101
+ is under the myworktree root), then ``myworktree'' will substitute for
102
+ {woktree}.
103
+
104
+ See also:
105
+
106
+ run
107
+ worktree
108
+
109
+ """
110
+ def __init__(self):
111
+ super().__init__('config')
112
+
113
+ def _add_config_parser(self, cls, project, parser_manager):
114
+ command = cls.get_managing_command()
115
+ config_key = command + '-config' if command else 'config'
116
+ config_parser = parser_manager.find_parser(config_key)
117
+
118
+ if not config_parser:
119
+ # Create a config parser under the managing command.
120
+ command_subparser_key = command + '-command' if command else 'command'
121
+ command_subparser = parser_manager.find_subparser(command_subparser_key)
122
+ if not command_subparser:
123
+ # This plugin doesn't have subcommands, so don't add one.
124
+ return
125
+
126
+ config_help = 'Configure ' + command if command else 'Configure git-project'
127
+ config_parser = parser_manager.add_parser(command_subparser,
128
+ 'config',
129
+ config_key,
130
+ help=config_help)
131
+
132
+ config_parser.set_defaults(func=command_config)
133
+ config_parser.set_defaults(getter=cls.get)
134
+ config_parser.set_defaults(exister=cls.exists)
135
+ config_parser.set_defaults(classname=cls.__name__)
136
+
137
+ if hasattr(cls, 'subsection'):
138
+ config_parser.set_defaults(subsection=cls.subsection())
139
+ config_parser.add_argument('ident', help=f'{cls.__name__} to modify')
140
+
141
+ if not command:
142
+ # This is the top-level 'config' command.
143
+ add_plugin_version_argument(config_parser)
144
+
145
+ config_parser.add_argument('name', help='Property name')
146
+ config_parser.add_argument('value', nargs='?', help='Property value to set')
147
+ config_parser.add_argument('--add', action='store_true',
148
+ help='Add a value to a property')
149
+ config_parser.add_argument('--unset', action='store_true',
150
+ help='Remove a value from a property')
151
+
152
+ def add_arguments(self,
153
+ git,
154
+ gitproject,
155
+ project,
156
+ parser_manager,
157
+ plugin_manager):
158
+ """Add arguments for 'git-project config'"""
159
+ self._add_config_parser(Project, project, parser_manager)
160
+
161
+ def modify_arguments(self, git, gitproject, project, parser_manager, plugin_manager):
162
+ """Modify arguments for 'git-project config.'"""
163
+
164
+ # Find all plugins with classes that derive from ConfigObject and add
165
+ # config commands to them.
166
+ for plugin in plugin_manager.iterplugins():
167
+ for cls in plugin.iterclasses():
168
+ if (issubclass(cls, ConfigObject)):
169
+ self._add_config_parser(cls, project, parser_manager)