git-project 0.0.26__tar.gz → 0.0.28__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.
- git_project-0.0.28/.#pyproject.toml +1 -0
- git_project-0.0.28/.git +1 -0
- {git_project-0.0.26 → git_project-0.0.28}/PKG-INFO +1 -1
- {git_project-0.0.26 → git_project-0.0.28}/_version.py +9 -4
- git_project-0.0.28/git_project-0.0.28.dev1+g2184a37-py3-none-any.whl +0 -0
- git_project-0.0.28/git_project-0.0.28.dev1+g2184a37.tar.gz +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/git.py +17 -8
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/substitutable.py +29 -13
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/test_support/common.py +2 -2
- git_project-0.0.28/test.out +131 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_git.py +57 -3
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_project.py +5 -2
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_substitutable.py +140 -0
- git_project-0.0.26/.git +0 -1
- git_project-0.0.26/build/lib/git_project/__init__.py +0 -33
- git_project-0.0.26/build/lib/git_project/commandline.py +0 -164
- git_project-0.0.26/build/lib/git_project/configobj.py +0 -300
- git_project-0.0.26/build/lib/git_project/exception.py +0 -30
- git_project-0.0.26/build/lib/git_project/git.py +0 -873
- git_project-0.0.26/build/lib/git_project/gitproject.py +0 -61
- git_project-0.0.26/build/lib/git_project/main.py +0 -63
- git_project-0.0.26/build/lib/git_project/parsermanager.py +0 -360
- git_project-0.0.26/build/lib/git_project/plugin.py +0 -118
- git_project-0.0.26/build/lib/git_project/pluginmanager.py +0 -54
- git_project-0.0.26/build/lib/git_project/project.py +0 -197
- git_project-0.0.26/build/lib/git_project/runnable.py +0 -71
- git_project-0.0.26/build/lib/git_project/scopedobj.py +0 -207
- git_project-0.0.26/build/lib/git_project/shell.py +0 -119
- git_project-0.0.26/build/lib/git_project/substitutable.py +0 -139
- git_project-0.0.26/test.out +0 -17
- {git_project-0.0.26 → git_project-0.0.28}/.gitignore +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/CONTRIBUTORS +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/COPYING +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/MANIFEST.in +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/Makefile +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/authors.rst +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/changelog.rst +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/conf.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/index.rst +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/intro.rst +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/license.rst +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/docs/make.bat +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/pyproject.toml +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/requirements.txt +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/__init__.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/commandline.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/configobj.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/exception.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/gitproject.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/main.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/parsermanager.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/plugin.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/pluginmanager.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/project.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/runnable.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/scopedobj.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/shell.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/src/git_project/test_support/__init__.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/conftest.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_confobj.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_gitproject.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_main.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_runnable.py +0 -0
- {git_project-0.0.26 → git_project-0.0.28}/tests/test_scopedobj.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dag@basie.2617:1746908671
|
git_project-0.0.28/.git
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
gitdir: /home/dag/src/git-project/.git/worktrees/dev/
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
# file generated by
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
|
5
|
+
|
|
3
6
|
TYPE_CHECKING = False
|
|
4
7
|
if TYPE_CHECKING:
|
|
5
|
-
from typing import Tuple
|
|
8
|
+
from typing import Tuple
|
|
9
|
+
from typing import Union
|
|
10
|
+
|
|
6
11
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
12
|
else:
|
|
8
13
|
VERSION_TUPLE = object
|
|
@@ -12,5 +17,5 @@ __version__: str
|
|
|
12
17
|
__version_tuple__: VERSION_TUPLE
|
|
13
18
|
version_tuple: VERSION_TUPLE
|
|
14
19
|
|
|
15
|
-
__version__ = version = '0.0.
|
|
16
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
20
|
+
__version__ = version = '0.0.28'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 0, 28)
|
|
Binary file
|
|
Binary file
|
|
@@ -396,7 +396,10 @@ class Git(object):
|
|
|
396
396
|
|
|
397
397
|
# Repository-wide info
|
|
398
398
|
def __init__(self):
|
|
399
|
-
|
|
399
|
+
self.reinit(Path.cwd())
|
|
400
|
+
|
|
401
|
+
def reinit(self, gitdir: Path):
|
|
402
|
+
repo_path = pygit2.discover_repository(gitdir)
|
|
400
403
|
if repo_path:
|
|
401
404
|
self._repo = pygit2.Repository(repo_path)
|
|
402
405
|
self._config = self.Config(self, self._repo.config)
|
|
@@ -461,16 +464,18 @@ class Git(object):
|
|
|
461
464
|
return self._repo.path
|
|
462
465
|
|
|
463
466
|
def get_git_common_dir(self):
|
|
464
|
-
"""Get the GIT_COMMON_DIR directory.
|
|
467
|
+
"""Get the GIT_COMMON_DIR directory."""
|
|
468
|
+
if not self.get_current_worktree():
|
|
469
|
+
return self.get_gitdir()
|
|
465
470
|
|
|
466
|
-
|
|
471
|
+
worktree_gitdir = Path(self._repo.path)
|
|
467
472
|
|
|
468
|
-
|
|
469
|
-
gitdir = Path(self._repo.path)
|
|
470
|
-
while gitdir.name != '.git':
|
|
471
|
-
gitdir = gitdir.parent
|
|
473
|
+
commondir_filename = worktree_gitdir / 'commondir'
|
|
472
474
|
|
|
473
|
-
|
|
475
|
+
with open(commondir_filename, 'r') as commondir_file:
|
|
476
|
+
commondir = commondir_file.read().strip()
|
|
477
|
+
|
|
478
|
+
return commondir
|
|
474
479
|
|
|
475
480
|
def get_current_worktree(self):
|
|
476
481
|
"""Return the name of the current worktree or None if we are not in a
|
|
@@ -556,6 +561,10 @@ class Git(object):
|
|
|
556
561
|
|
|
557
562
|
# Operations on remotes
|
|
558
563
|
|
|
564
|
+
def get_remote_url(self, remote):
|
|
565
|
+
"""Get the URL for the given remote."""
|
|
566
|
+
return self._repo.remotes[remote].url
|
|
567
|
+
|
|
559
568
|
def set_remote_fetch_refspecs(self, remote, refspecs):
|
|
560
569
|
"""Set the refspec list for the given remote to refspecs."""
|
|
561
570
|
if isinstance(refspecs, str):
|
|
@@ -64,28 +64,18 @@ class SubstitutableConfigObject(ConfigObject):
|
|
|
64
64
|
|
|
65
65
|
# Substitute for project-global values.
|
|
66
66
|
for key, value in project.iteritems():
|
|
67
|
-
if key == 'path':
|
|
68
|
-
found_path = True
|
|
69
67
|
if key == self.get_subsection():
|
|
70
68
|
value = self.get_ident()
|
|
71
69
|
formats[key] = value
|
|
72
70
|
|
|
73
71
|
# Substitute for values in self.
|
|
74
72
|
for key, value in self.iteritems():
|
|
75
|
-
if key == 'path':
|
|
76
|
-
found_path = True
|
|
77
73
|
formats[key] = value
|
|
78
74
|
|
|
79
75
|
formats['project'] = project.get_section()
|
|
80
|
-
formats['gitdir'] = git.get_gitdir()
|
|
81
|
-
formats['git_common_dir'] = git.get_git_common_dir()
|
|
82
|
-
|
|
83
|
-
if not found_path:
|
|
84
|
-
# We haven't found a worktree or other construct to give us a path,
|
|
85
|
-
# so do a mildly expensive thing to get the path of the curernt
|
|
86
|
-
# working copy.
|
|
87
|
-
path = git.get_working_copy_root()
|
|
88
|
-
formats['path'] = path
|
|
76
|
+
formats['gitdir'] = str(git.get_gitdir())
|
|
77
|
+
formats['git_common_dir'] = str(git.get_git_common_dir())
|
|
78
|
+
formats['git_workdir'] = str(git.get_working_copy_root())
|
|
89
79
|
|
|
90
80
|
current_branch = git.get_current_branch()
|
|
91
81
|
if not current_branch:
|
|
@@ -107,6 +97,19 @@ class SubstitutableConfigObject(ConfigObject):
|
|
|
107
97
|
|
|
108
98
|
formats['branch'] = current_branch
|
|
109
99
|
|
|
100
|
+
# Make sure substitutions don't reference themselves, to avoid an
|
|
101
|
+
# infinite loop substituting.
|
|
102
|
+
#
|
|
103
|
+
# NOTE: This won't catch mutually-recursive situations like:
|
|
104
|
+
#
|
|
105
|
+
# path: {dir}/foo
|
|
106
|
+
# dir: {path}/bar
|
|
107
|
+
for key, value in formats.items():
|
|
108
|
+
if f'{{{key}}}' in value:
|
|
109
|
+
raise RuntimeError(
|
|
110
|
+
f'Recursive substitution: {key} is in {value}'
|
|
111
|
+
)
|
|
112
|
+
|
|
110
113
|
def try_format(string, formats):
|
|
111
114
|
return eval(f"f'{string}'", formats)
|
|
112
115
|
|
|
@@ -116,7 +119,17 @@ class SubstitutableConfigObject(ConfigObject):
|
|
|
116
119
|
value = scope.get_ident()
|
|
117
120
|
formats[key] = value
|
|
118
121
|
|
|
122
|
+
# Allow escaping braces by surrounding each brace with braces. This is
|
|
123
|
+
# not valid f-string syntax and is unlikely to be used in ordinary
|
|
124
|
+
# config values. Replace with an equally unlikely sequence, then
|
|
125
|
+
# substitute on that string.
|
|
126
|
+
|
|
127
|
+
escaped_braces = False
|
|
119
128
|
while True:
|
|
129
|
+
escaped_braces = escaped_braces or '{{}' in string or '{}}' in string
|
|
130
|
+
if escaped_braces:
|
|
131
|
+
string = string.replace('{{}', '[[[')
|
|
132
|
+
string = string.replace('{}}', ']]]')
|
|
120
133
|
try:
|
|
121
134
|
newstring = try_format(string, formats)
|
|
122
135
|
except KeyError as exception:
|
|
@@ -137,6 +150,9 @@ class SubstitutableConfigObject(ConfigObject):
|
|
|
137
150
|
changed = False if newstring == string else True
|
|
138
151
|
string = newstring
|
|
139
152
|
if not changed:
|
|
153
|
+
if escaped_braces:
|
|
154
|
+
string = string.replace('[[[', '{')
|
|
155
|
+
string = string.replace(']]]', '}')
|
|
140
156
|
break
|
|
141
157
|
|
|
142
158
|
return string
|
|
@@ -323,9 +323,9 @@ def init_clone(url, path):
|
|
|
323
323
|
|
|
324
324
|
remote_only_commit = repo.revparse_single('refs/remotes/origin/remote_only')
|
|
325
325
|
|
|
326
|
-
|
|
326
|
+
pushed_remote_only_branch = repo.branches.create('pushed_remote_only', remote_only_commit)
|
|
327
327
|
|
|
328
|
-
# -------merged_remote, origin/old_master--origin/master, pushed_indirectly--origin/remote_only,
|
|
328
|
+
# -------merged_remote, origin/old_master--origin/master, pushed_indirectly--origin/remote_only, pushed_remote_only
|
|
329
329
|
# | \
|
|
330
330
|
# | `---master, merged_local--unmerged
|
|
331
331
|
# \
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
============================= test session starts ==============================
|
|
2
|
+
platform linux -- Python 3.11.9, pytest-8.2.2, pluggy-1.5.0
|
|
3
|
+
rootdir: /home/dag/src/git-project/dev
|
|
4
|
+
configfile: pyproject.toml
|
|
5
|
+
plugins: anyio-4.3.0, console-scripts-1.4.1
|
|
6
|
+
collected 106 items
|
|
7
|
+
|
|
8
|
+
tests/test_confobj.py ............ [ 11%]
|
|
9
|
+
tests/test_git.py .......................FF............................ [ 61%]
|
|
10
|
+
tests/test_gitproject.py .. [ 63%]
|
|
11
|
+
tests/test_main.py . [ 64%]
|
|
12
|
+
tests/test_project.py ........... [ 74%]
|
|
13
|
+
tests/test_runnable.py ........ [ 82%]
|
|
14
|
+
tests/test_scopedobj.py ..... [ 86%]
|
|
15
|
+
tests/test_substitutable.py .............. [100%]
|
|
16
|
+
|
|
17
|
+
=================================== FAILURES ===================================
|
|
18
|
+
________________________________ test_git_clone ________________________________
|
|
19
|
+
|
|
20
|
+
reset_directory = None
|
|
21
|
+
remote_repository = pygit2.Repository('/tmp/pytest-of-dag/pytest-14/local_remote_test_git_clone.git0/')
|
|
22
|
+
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x7ff199ba1e50>, _basetemp=PosixPath('/tmp/pytest-of-dag/pytest-14'), _retention_count=3, _retention_policy='all')
|
|
23
|
+
|
|
24
|
+
def test_git_clone(reset_directory, remote_repository, tmp_path_factory):
|
|
25
|
+
path = tmp_path_factory.mktemp('clone-workdir')
|
|
26
|
+
|
|
27
|
+
os.chdir(path)
|
|
28
|
+
|
|
29
|
+
git = git_project.Git()
|
|
30
|
+
|
|
31
|
+
remote_url = 'file://' + remote_repository.path
|
|
32
|
+
|
|
33
|
+
> clone_path = git.clone(remote_url)
|
|
34
|
+
|
|
35
|
+
/home/dag/src/git-project/dev/tests/test_git.py:441:
|
|
36
|
+
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
37
|
+
/home/dag/src/git-project/dev/src/git_project/git.py:744: in clone
|
|
38
|
+
self._repo = pygit2.clone_repository(url, target_path, bare, callbacks=callbacks)
|
|
39
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/__init__.py:217: in clone_repository
|
|
40
|
+
payload.check_error(err)
|
|
41
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/callbacks.py:93: in check_error
|
|
42
|
+
raise self._stored_exception
|
|
43
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/callbacks.py:424: in wrapper
|
|
44
|
+
return f(*args)
|
|
45
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/callbacks.py:552: in _transfer_progress_cb
|
|
46
|
+
transfer_progress(TransferProgress(stats_ptr))
|
|
47
|
+
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
48
|
+
|
|
49
|
+
self = <git_project.git.Git.RemoteCallbacks object at 0x7ff199a06950>
|
|
50
|
+
stats = <pygit2.remotes.TransferProgress object at 0x7ff199a9f790>
|
|
51
|
+
|
|
52
|
+
def transfer_progress(self, stats):
|
|
53
|
+
if not self.started_transfer:
|
|
54
|
+
self.started_transfer = True
|
|
55
|
+
print(f'Receiving objects ({stats.total_objects})...')
|
|
56
|
+
> self.progress.start(max_value=stats.total_objects)
|
|
57
|
+
E TypeError: ProgressBar.start() got an unexpected keyword argument 'max_value'
|
|
58
|
+
|
|
59
|
+
/home/dag/src/git-project/dev/src/git_project/git.py:77: TypeError
|
|
60
|
+
----------------------------- Captured stdout call -----------------------------
|
|
61
|
+
Remote: Counting objects 1
|
|
62
|
+
Remote: Counting objects 9
|
|
63
|
+
Remote: Counting objects 14
|
|
64
|
+
Remote: Counting objects 14
|
|
65
|
+
|
|
66
|
+
Remote: Compressing objects: 0% (0/14)
|
|
67
|
+
Remote: Compressing objects: 100% (14/14), done
|
|
68
|
+
|
|
69
|
+
Receiving objects (14)...
|
|
70
|
+
___________________________ test_git_clone_with_path ___________________________
|
|
71
|
+
|
|
72
|
+
reset_directory = None
|
|
73
|
+
remote_repository = pygit2.Repository('/tmp/pytest-of-dag/pytest-14/local_remote_test_git_clone_with_path.git0/')
|
|
74
|
+
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x7ff199ba1e50>, _basetemp=PosixPath('/tmp/pytest-of-dag/pytest-14'), _retention_count=3, _retention_policy='all')
|
|
75
|
+
|
|
76
|
+
def test_git_clone_with_path(reset_directory,
|
|
77
|
+
remote_repository,
|
|
78
|
+
tmp_path_factory):
|
|
79
|
+
path = tmp_path_factory.mktemp('clone-workdir')
|
|
80
|
+
os.chdir(path)
|
|
81
|
+
|
|
82
|
+
git = git_project.Git()
|
|
83
|
+
|
|
84
|
+
remote_url = 'file://' + remote_repository.path
|
|
85
|
+
|
|
86
|
+
path = Path.cwd() / 'foo' / 'bar'
|
|
87
|
+
|
|
88
|
+
os.makedirs(path)
|
|
89
|
+
|
|
90
|
+
path = path / 'test-clone'
|
|
91
|
+
|
|
92
|
+
> clone_path = git.clone(remote_url, path)
|
|
93
|
+
|
|
94
|
+
/home/dag/src/git-project/dev/tests/test_git.py:482:
|
|
95
|
+
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
96
|
+
/home/dag/src/git-project/dev/src/git_project/git.py:744: in clone
|
|
97
|
+
self._repo = pygit2.clone_repository(url, target_path, bare, callbacks=callbacks)
|
|
98
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/__init__.py:217: in clone_repository
|
|
99
|
+
payload.check_error(err)
|
|
100
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/callbacks.py:93: in check_error
|
|
101
|
+
raise self._stored_exception
|
|
102
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/callbacks.py:424: in wrapper
|
|
103
|
+
return f(*args)
|
|
104
|
+
/home/dag/.virtualenvs/dev/lib/python3.11/site-packages/pygit2/callbacks.py:552: in _transfer_progress_cb
|
|
105
|
+
transfer_progress(TransferProgress(stats_ptr))
|
|
106
|
+
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
|
107
|
+
|
|
108
|
+
self = <git_project.git.Git.RemoteCallbacks object at 0x7ff198a8e350>
|
|
109
|
+
stats = <pygit2.remotes.TransferProgress object at 0x7ff198a8eb10>
|
|
110
|
+
|
|
111
|
+
def transfer_progress(self, stats):
|
|
112
|
+
if not self.started_transfer:
|
|
113
|
+
self.started_transfer = True
|
|
114
|
+
print(f'Receiving objects ({stats.total_objects})...')
|
|
115
|
+
> self.progress.start(max_value=stats.total_objects)
|
|
116
|
+
E TypeError: ProgressBar.start() got an unexpected keyword argument 'max_value'
|
|
117
|
+
|
|
118
|
+
/home/dag/src/git-project/dev/src/git_project/git.py:77: TypeError
|
|
119
|
+
----------------------------- Captured stdout call -----------------------------
|
|
120
|
+
Remote: Counting objects 1
|
|
121
|
+
Remote: Counting objects 14
|
|
122
|
+
Remote: Counting objects 14
|
|
123
|
+
|
|
124
|
+
Remote: Compressing objects: 0% (0/14)
|
|
125
|
+
Remote: Compressing objects: 100% (14/14), done
|
|
126
|
+
|
|
127
|
+
Receiving objects (14)...
|
|
128
|
+
=========================== short test summary info ============================
|
|
129
|
+
FAILED tests/test_git.py::test_git_clone - TypeError: ProgressBar.start() got...
|
|
130
|
+
FAILED tests/test_git.py::test_git_clone_with_path - TypeError: ProgressBar.s...
|
|
131
|
+
======================== 2 failed, 104 passed in 2.74s =========================
|
|
@@ -391,10 +391,10 @@ def test_git_iterrefnames(reset_directory, local_repository):
|
|
|
391
391
|
['refs/heads/master',
|
|
392
392
|
'refs/heads/merged_local',
|
|
393
393
|
'refs/heads/merged_remote',
|
|
394
|
-
'refs/heads/merged_remote_only',
|
|
395
394
|
'refs/heads/notpushed',
|
|
396
395
|
'refs/heads/pushed',
|
|
397
396
|
'refs/heads/pushed_indirectly',
|
|
397
|
+
'refs/heads/pushed_remote_only',
|
|
398
398
|
'refs/heads/unmerged'])
|
|
399
399
|
|
|
400
400
|
def test_git_iterrefnames_str(reset_directory, local_repository):
|
|
@@ -408,10 +408,10 @@ def test_git_iterrefnames_str(reset_directory, local_repository):
|
|
|
408
408
|
['refs/heads/master',
|
|
409
409
|
'refs/heads/merged_local',
|
|
410
410
|
'refs/heads/merged_remote',
|
|
411
|
-
'refs/heads/merged_remote_only',
|
|
412
411
|
'refs/heads/notpushed',
|
|
413
412
|
'refs/heads/pushed',
|
|
414
413
|
'refs/heads/pushed_indirectly',
|
|
414
|
+
'refs/heads/pushed_remote_only',
|
|
415
415
|
'refs/heads/unmerged'])
|
|
416
416
|
|
|
417
417
|
def test_git_create_branch(reset_directory, local_repository):
|
|
@@ -668,10 +668,10 @@ def test_git_iterbranches(reset_directory, git):
|
|
|
668
668
|
assert branches == {'master',
|
|
669
669
|
'merged_local',
|
|
670
670
|
'merged_remote',
|
|
671
|
-
'merged_remote_only',
|
|
672
671
|
'notpushed',
|
|
673
672
|
'pushed',
|
|
674
673
|
'pushed_indirectly',
|
|
674
|
+
'pushed_remote_only',
|
|
675
675
|
'unmerged',
|
|
676
676
|
'origin/HEAD',
|
|
677
677
|
'origin/master',
|
|
@@ -820,3 +820,57 @@ def test_git_worktree_get_current_worktree(reset_directory, local_repository):
|
|
|
820
820
|
wtgit = git_project.Git()
|
|
821
821
|
|
|
822
822
|
assert wtgit.get_current_worktree() == 'test-wt'
|
|
823
|
+
|
|
824
|
+
def test_git_get_remote_url(reset_directory, local_repository, remote_repository):
|
|
825
|
+
os.chdir(local_repository.path)
|
|
826
|
+
|
|
827
|
+
git = git_project.Git()
|
|
828
|
+
|
|
829
|
+
assert git.has_repo()
|
|
830
|
+
|
|
831
|
+
url = git.get_remote_url('origin')
|
|
832
|
+
|
|
833
|
+
assert url == remote_repository.path
|
|
834
|
+
|
|
835
|
+
def test_git_reinit(local_repository):
|
|
836
|
+
repo_parent = Path(local_repository.path).parent
|
|
837
|
+
|
|
838
|
+
os.chdir(local_repository.path)
|
|
839
|
+
|
|
840
|
+
git = git_project.Git()
|
|
841
|
+
|
|
842
|
+
assert git.has_repo()
|
|
843
|
+
assert Path(git.get_gitdir()) == Path(local_repository.path)
|
|
844
|
+
|
|
845
|
+
new_hidden_dir = '.test.git'
|
|
846
|
+
|
|
847
|
+
gitdir = Path(git.get_gitdir())
|
|
848
|
+
newgitdir = repo_parent / new_hidden_dir
|
|
849
|
+
|
|
850
|
+
gitdir.rename(newgitdir)
|
|
851
|
+
|
|
852
|
+
git.reinit(newgitdir)
|
|
853
|
+
|
|
854
|
+
assert git.has_repo()
|
|
855
|
+
assert Path(git.get_gitdir()) == repo_parent / new_hidden_dir
|
|
856
|
+
|
|
857
|
+
def test_git_get_git_common_dir_renamed(reset_directory, local_repository):
|
|
858
|
+
repo_parent = Path(local_repository.path).parent
|
|
859
|
+
|
|
860
|
+
os.chdir(local_repository.path)
|
|
861
|
+
|
|
862
|
+
git = git_project.Git()
|
|
863
|
+
|
|
864
|
+
assert git.has_repo()
|
|
865
|
+
|
|
866
|
+
new_hidden_dir = '.test.git'
|
|
867
|
+
|
|
868
|
+
gitdir = Path(git.get_gitdir())
|
|
869
|
+
newgitdir = repo_parent / new_hidden_dir
|
|
870
|
+
|
|
871
|
+
gitdir.rename(newgitdir)
|
|
872
|
+
|
|
873
|
+
git.reinit(newgitdir)
|
|
874
|
+
|
|
875
|
+
assert git.has_repo()
|
|
876
|
+
assert Path(git.get_git_common_dir()).name == new_hidden_dir
|
|
@@ -77,6 +77,7 @@ def test_project_add_branch(project):
|
|
|
77
77
|
assert branches == {'master', 'project', 'remote_only'}
|
|
78
78
|
|
|
79
79
|
def test_project_iterrefnames(project):
|
|
80
|
+
print(f'In {Path.cwd()}')
|
|
80
81
|
project.add_branch('pushed')
|
|
81
82
|
|
|
82
83
|
branches = {branch for branch in project.iterbranches()}
|
|
@@ -93,6 +94,7 @@ def test_project_iterrefnames(project):
|
|
|
93
94
|
'refs/remotes/origin/master',
|
|
94
95
|
'refs/heads/pushed',
|
|
95
96
|
'refs/heads/pushed_indirectly',
|
|
97
|
+
'refs/heads/pushed_remote_only',
|
|
96
98
|
'refs/remotes/origin/pushed',
|
|
97
99
|
'refs/remotes/origin/remote_only'}
|
|
98
100
|
|
|
@@ -104,7 +106,8 @@ def test_project_branch_is_merged(project):
|
|
|
104
106
|
assert project.branch_is_merged('merged_local')
|
|
105
107
|
assert not project.branch_is_merged('unmerged')
|
|
106
108
|
assert project.branch_is_merged('merged_remote')
|
|
107
|
-
|
|
109
|
+
# FIXME: Is not really merged!
|
|
110
|
+
assert project.branch_is_merged('pushed_remote_only')
|
|
108
111
|
|
|
109
112
|
def test_project_branch_is_pushed(project):
|
|
110
113
|
assert not project.branch_is_pushed('master')
|
|
@@ -113,7 +116,7 @@ def test_project_branch_is_pushed(project):
|
|
|
113
116
|
assert project.branch_is_pushed('merged_remote')
|
|
114
117
|
assert not project.branch_is_pushed('merged_local')
|
|
115
118
|
assert not project.branch_is_pushed('unmerged')
|
|
116
|
-
assert project.branch_is_pushed('
|
|
119
|
+
assert project.branch_is_pushed('pushed_remote_only')
|
|
117
120
|
|
|
118
121
|
def test_project_prune_branch(reset_directory,
|
|
119
122
|
remote_repository,
|
|
@@ -25,6 +25,7 @@ from git_project.test_support import check_config_file
|
|
|
25
25
|
|
|
26
26
|
import os
|
|
27
27
|
from pathlib import Path
|
|
28
|
+
import pytest
|
|
28
29
|
import shutil
|
|
29
30
|
|
|
30
31
|
class MySubstitutable(git_project.SubstitutableConfigObject):
|
|
@@ -402,3 +403,142 @@ def test_substitutable_substitute_fstring(reset_directory, git):
|
|
|
402
403
|
substitutable.command)
|
|
403
404
|
|
|
404
405
|
assert command == f'cd {project.builddir}/{current_branch.replace("imerge/", "", 1)} && make {project.target}'
|
|
406
|
+
|
|
407
|
+
def test_substitutable_substitute_recursive(reset_directory, git):
|
|
408
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
409
|
+
def __init__(self):
|
|
410
|
+
super().__init__(git,
|
|
411
|
+
'project',
|
|
412
|
+
None,
|
|
413
|
+
'myproject',
|
|
414
|
+
builddir='/path/to/{builddir}',
|
|
415
|
+
target='debug')
|
|
416
|
+
|
|
417
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
418
|
+
|
|
419
|
+
project = MyProject()
|
|
420
|
+
|
|
421
|
+
with pytest.raises(Exception) as e:
|
|
422
|
+
command = substitutable.substitute_value(git,
|
|
423
|
+
project,
|
|
424
|
+
substitutable.command)
|
|
425
|
+
|
|
426
|
+
def test_substitutable_substitute_project(reset_directory, git):
|
|
427
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
428
|
+
def __init__(self):
|
|
429
|
+
super().__init__(git,
|
|
430
|
+
'project',
|
|
431
|
+
None,
|
|
432
|
+
'myproject',
|
|
433
|
+
builddir='/path/to/build/{project}',
|
|
434
|
+
target='debug')
|
|
435
|
+
|
|
436
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
437
|
+
|
|
438
|
+
project = MyProject()
|
|
439
|
+
|
|
440
|
+
command = substitutable.substitute_value(git,
|
|
441
|
+
project,
|
|
442
|
+
substitutable.command)
|
|
443
|
+
|
|
444
|
+
assert command == f'cd /path/to/build/{project.get_section()}/{git.get_current_branch()} && make {project.target}'
|
|
445
|
+
|
|
446
|
+
def test_substitutable_substitute_gitdir(reset_directory, git):
|
|
447
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
448
|
+
def __init__(self):
|
|
449
|
+
super().__init__(git,
|
|
450
|
+
'project',
|
|
451
|
+
None,
|
|
452
|
+
'myproject',
|
|
453
|
+
builddir='{gitdir}/../path/to/build',
|
|
454
|
+
target='debug')
|
|
455
|
+
|
|
456
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
457
|
+
|
|
458
|
+
project = MyProject()
|
|
459
|
+
|
|
460
|
+
command = substitutable.substitute_value(git,
|
|
461
|
+
project,
|
|
462
|
+
substitutable.command)
|
|
463
|
+
|
|
464
|
+
assert command == f'cd {git.get_gitdir()}/../path/to/build/{git.get_current_branch()} && make {project.target}'
|
|
465
|
+
|
|
466
|
+
def test_substitutable_substitute_git_common_dir(reset_directory, git):
|
|
467
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
468
|
+
def __init__(self):
|
|
469
|
+
super().__init__(git,
|
|
470
|
+
'project',
|
|
471
|
+
None,
|
|
472
|
+
'myproject',
|
|
473
|
+
builddir='{git_common_dir}/../path/to/build',
|
|
474
|
+
target='debug')
|
|
475
|
+
|
|
476
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
477
|
+
|
|
478
|
+
project = MyProject()
|
|
479
|
+
|
|
480
|
+
command = substitutable.substitute_value(git,
|
|
481
|
+
project,
|
|
482
|
+
substitutable.command)
|
|
483
|
+
|
|
484
|
+
assert command == f'cd {git.get_git_common_dir()}/../path/to/build/{git.get_current_branch()} && make {project.target}'
|
|
485
|
+
|
|
486
|
+
def test_substitutable_substitute_git_workdir(reset_directory, git):
|
|
487
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
488
|
+
def __init__(self):
|
|
489
|
+
super().__init__(git,
|
|
490
|
+
'project',
|
|
491
|
+
None,
|
|
492
|
+
'myproject',
|
|
493
|
+
builddir='{git_workdir}/path/to/build',
|
|
494
|
+
target='debug')
|
|
495
|
+
|
|
496
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
497
|
+
|
|
498
|
+
project = MyProject()
|
|
499
|
+
|
|
500
|
+
command = substitutable.substitute_value(git,
|
|
501
|
+
project,
|
|
502
|
+
substitutable.command)
|
|
503
|
+
|
|
504
|
+
assert command == f'cd {git.get_working_copy_root()}/path/to/build/{git.get_current_branch()} && make {project.target}'
|
|
505
|
+
|
|
506
|
+
def test_substitutable_substitute_escaped_braces(reset_directory, git):
|
|
507
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
508
|
+
def __init__(self):
|
|
509
|
+
super().__init__(git,
|
|
510
|
+
'project',
|
|
511
|
+
None,
|
|
512
|
+
'myproject',
|
|
513
|
+
builddir='{git_workdir}/{{}path{}}/to/build',
|
|
514
|
+
target='debug')
|
|
515
|
+
|
|
516
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
517
|
+
|
|
518
|
+
project = MyProject()
|
|
519
|
+
|
|
520
|
+
command = substitutable.substitute_value(git,
|
|
521
|
+
project,
|
|
522
|
+
substitutable.command)
|
|
523
|
+
|
|
524
|
+
assert command == f'cd {git.get_working_copy_root()}/{{path}}/to/build/{git.get_current_branch()} && make {project.target}'
|
|
525
|
+
|
|
526
|
+
def test_substitutable_substitute_preserve_escaped_braces(reset_directory, git):
|
|
527
|
+
class MyProject(git_project.ScopedConfigObject):
|
|
528
|
+
def __init__(self):
|
|
529
|
+
super().__init__(git,
|
|
530
|
+
'project',
|
|
531
|
+
None,
|
|
532
|
+
'myproject',
|
|
533
|
+
builddir='{git_workdir}/{{}{{}{}}path{{}{}}{}}/to/build',
|
|
534
|
+
target='debug')
|
|
535
|
+
|
|
536
|
+
substitutable = MySubstitutable.get(git, 'project', 'test')
|
|
537
|
+
|
|
538
|
+
project = MyProject()
|
|
539
|
+
|
|
540
|
+
command = substitutable.substitute_value(git,
|
|
541
|
+
project,
|
|
542
|
+
substitutable.command)
|
|
543
|
+
|
|
544
|
+
assert command == f'cd {git.get_working_copy_root()}/{{{{}}path{{}}}}/to/build/{git.get_current_branch()} && make {project.target}'
|
git_project-0.0.26/.git
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
gitdir: /Users/dag/projects/git-project/.git/worktrees/master/
|
|
@@ -1,33 +0,0 @@
|
|
|
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 .commandline import parse_arguments, add_top_level_command
|
|
20
|
-
from .commandline import get_or_add_top_level_command
|
|
21
|
-
from .configobj import ConfigObject
|
|
22
|
-
from .exception import GitProjectException
|
|
23
|
-
from .git import Git
|
|
24
|
-
from .gitproject import GitProject
|
|
25
|
-
from .main import main_impl
|
|
26
|
-
from .parsermanager import ParserManager
|
|
27
|
-
from .plugin import Plugin
|
|
28
|
-
from .pluginmanager import PluginManager
|
|
29
|
-
from .project import Project
|
|
30
|
-
from .runnable import RunnableConfigObject
|
|
31
|
-
from .scopedobj import ScopedConfigObject
|
|
32
|
-
from .substitutable import SubstitutableConfigObject
|
|
33
|
-
from .shell import run_command_with_shell, iter_command, capture_command
|