gitlabber 1.2.7__tar.gz → 1.2.8__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 (54) hide show
  1. {gitlabber-1.2.7/gitlabber.egg-info → gitlabber-1.2.8}/PKG-INFO +5 -5
  2. {gitlabber-1.2.7 → gitlabber-1.2.8}/README.rst +2 -3
  3. gitlabber-1.2.8/gitlabber/__init__.py +2 -0
  4. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/cli.py +1 -7
  5. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/gitlab_tree.py +27 -16
  6. {gitlabber-1.2.7 → gitlabber-1.2.8/gitlabber.egg-info}/PKG-INFO +5 -5
  7. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber.egg-info/SOURCES.txt +1 -13
  8. {gitlabber-1.2.7 → gitlabber-1.2.8}/pyproject.toml +24 -2
  9. gitlabber-1.2.8/setup.cfg +10 -0
  10. gitlabber-1.2.8/setup.py +3 -0
  11. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/gitlab_test_utils.py +16 -5
  12. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_e2e.py +16 -6
  13. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_gitlab_tree.py +73 -1
  14. gitlabber-1.2.7/gitlabber/__init__.py +0 -2
  15. gitlabber-1.2.7/setup.cfg +0 -24
  16. gitlabber-1.2.7/setup.py +0 -90
  17. gitlabber-1.2.7/tests/__pycache__/__init__.cpython-311.pyc +0 -0
  18. gitlabber-1.2.7/tests/__pycache__/gitlab_test_utils.cpython-311.pyc +0 -0
  19. gitlabber-1.2.7/tests/__pycache__/io_test_util.cpython-311.pyc +0 -0
  20. gitlabber-1.2.7/tests/__pycache__/test_archive.cpython-311-pytest-8.2.2.pyc +0 -0
  21. gitlabber-1.2.7/tests/__pycache__/test_cli.cpython-311-pytest-8.2.2.pyc +0 -0
  22. gitlabber-1.2.7/tests/__pycache__/test_e2e.cpython-311-pytest-8.2.2.pyc +0 -0
  23. gitlabber-1.2.7/tests/__pycache__/test_format.cpython-311-pytest-8.2.2.pyc +0 -0
  24. gitlabber-1.2.7/tests/__pycache__/test_git.cpython-311-pytest-8.2.2.pyc +0 -0
  25. gitlabber-1.2.7/tests/__pycache__/test_gitlab_tree.cpython-311-pytest-8.2.2.pyc +0 -0
  26. gitlabber-1.2.7/tests/__pycache__/test_integration.cpython-311-pytest-8.2.2.pyc +0 -0
  27. gitlabber-1.2.7/tests/__pycache__/test_method.cpython-311-pytest-8.2.2.pyc +0 -0
  28. gitlabber-1.2.7/tests/__pycache__/test_naming.cpython-311-pytest-8.2.2.pyc +0 -0
  29. {gitlabber-1.2.7 → gitlabber-1.2.8}/LICENSE.txt +0 -0
  30. {gitlabber-1.2.7 → gitlabber-1.2.8}/MANIFEST.in +0 -0
  31. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/__main__.py +0 -0
  32. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/archive.py +0 -0
  33. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/format.py +0 -0
  34. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/git.py +0 -0
  35. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/method.py +0 -0
  36. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/naming.py +0 -0
  37. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber/progress.py +0 -0
  38. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber.egg-info/dependency_links.txt +0 -0
  39. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber.egg-info/entry_points.txt +0 -0
  40. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber.egg-info/requires.txt +0 -0
  41. {gitlabber-1.2.7 → gitlabber-1.2.8}/gitlabber.egg-info/top_level.txt +0 -0
  42. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/__init__.py +0 -0
  43. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/io_test_util.py +0 -0
  44. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test-input.yaml +0 -0
  45. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test-output.json +0 -0
  46. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test-output.tree +0 -0
  47. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test-output.yaml +0 -0
  48. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_archive.py +0 -0
  49. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_cli.py +0 -0
  50. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_format.py +0 -0
  51. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_git.py +0 -0
  52. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_integration.py +0 -0
  53. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_method.py +0 -0
  54. {gitlabber-1.2.7 → gitlabber-1.2.8}/tests/test_naming.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: gitlabber
3
- Version: 1.2.7
3
+ Version: 1.2.8
4
4
  Summary: A Gitlab clone/pull utility for backing up or cloning Gitlab groups
5
5
  Author-email: Erez Mazor <erezmazor@gmail.com>
6
6
  License: MIT
@@ -34,6 +34,7 @@ Requires-Dist: coverage; extra == "test"
34
34
  Requires-Dist: pytest; extra == "test"
35
35
  Requires-Dist: pytest-cov; extra == "test"
36
36
  Requires-Dist: pytest-integration; extra == "test"
37
+ Dynamic: license-file
37
38
 
38
39
  .. image:: https://github.com/ezbz/gitlabber/actions/workflows/python-app.yml/badge.svg?branch=master
39
40
  :target: https://github.com/ezbz/gitlabber/actions/workflows/python-app.yml
@@ -51,7 +52,7 @@ Requires-Dist: pytest-integration; extra == "test"
51
52
  :target: https://pypi.python.org/pypi/gitlabber/
52
53
 
53
54
  .. image:: https://readthedocs.org/projects/gitlabber/badge/?version=latest&style=plastic
54
- :target: https://gitlabber.readthedocs.io/en/latest/README.html
55
+ :target: https://app.readthedocs.org/projects/gitlabber/
55
56
 
56
57
 
57
58
  Gitlabber
@@ -156,7 +157,6 @@ Usage
156
157
  comma delimited list of glob patterns of paths to projects or groups to exclude from clone/pull
157
158
  -r, --recursive clone/pull git submodules recursively
158
159
  -F, --use-fetch clone/fetch git repository (mirrored repositories)
159
- -d, --dont-checkout don't checkout pulled git repository
160
160
  -s, --include-shared include shared projects in the results
161
161
  -g term, --group-search term
162
162
  only include groups matching the search term, filtering done at the API level (useful for large projects, see: https://docs.gitlab.com/ee/api/groups.html#search-for-group works with partial names of path or name)
@@ -185,7 +185,7 @@ Usage
185
185
  clone projects that start with a case insensitive 'w' using a regular expression:
186
186
  gitlabber -i '/{[w].*}' .
187
187
 
188
- clone a user's personal projects to username-personal-projects
188
+ clone the personal projects to username-personal-projects
189
189
  gitlabber -U .
190
190
 
191
191
  perform a shallow clone of the git repositories
@@ -14,7 +14,7 @@
14
14
  :target: https://pypi.python.org/pypi/gitlabber/
15
15
 
16
16
  .. image:: https://readthedocs.org/projects/gitlabber/badge/?version=latest&style=plastic
17
- :target: https://gitlabber.readthedocs.io/en/latest/README.html
17
+ :target: https://app.readthedocs.org/projects/gitlabber/
18
18
 
19
19
 
20
20
  Gitlabber
@@ -119,7 +119,6 @@ Usage
119
119
  comma delimited list of glob patterns of paths to projects or groups to exclude from clone/pull
120
120
  -r, --recursive clone/pull git submodules recursively
121
121
  -F, --use-fetch clone/fetch git repository (mirrored repositories)
122
- -d, --dont-checkout don't checkout pulled git repository
123
122
  -s, --include-shared include shared projects in the results
124
123
  -g term, --group-search term
125
124
  only include groups matching the search term, filtering done at the API level (useful for large projects, see: https://docs.gitlab.com/ee/api/groups.html#search-for-group works with partial names of path or name)
@@ -148,7 +147,7 @@ Usage
148
147
  clone projects that start with a case insensitive 'w' using a regular expression:
149
148
  gitlabber -i '/{[w].*}' .
150
149
 
151
- clone a user's personal projects to username-personal-projects
150
+ clone the personal projects to username-personal-projects
152
151
  gitlabber -U .
153
152
 
154
153
  perform a shallow clone of the git repositories
@@ -0,0 +1,2 @@
1
+ """ Gitlabber """
2
+ __version__ = '1.2.8'
@@ -92,7 +92,7 @@ def parse_args(argv=None):
92
92
  clone projects that start with a case insensitive 'w' using a regular expression:
93
93
  gitlabber -i '/{[w].*}' .
94
94
 
95
- clone a user's personal projects to username-personal-projects
95
+ clone the user personal projects to username-personal-projects
96
96
  gitlabber -U .
97
97
 
98
98
  perform a shallow clone of the git repositories
@@ -199,12 +199,6 @@ def parse_args(argv=None):
199
199
  action='store_true',
200
200
  default=False,
201
201
  help='clone/fetch git repository (mirrored repositories)')
202
- parser.add_argument(
203
- '-d',
204
- '--dont-checkout',
205
- action='store_true',
206
- default=False,
207
- help="don't checkout pulled git repository")
208
202
  parser.add_argument(
209
203
  '-s',
210
204
  '--include-shared',
@@ -119,26 +119,37 @@ class GitlabTree:
119
119
  projects = group.projects.list(archived=self.archived, with_shared=self.include_shared, get_all=True)
120
120
  self.progress.update_progress_length(len(projects))
121
121
  self.add_projects(parent, projects)
122
+
123
+ if self.include_shared and hasattr(group, 'shared_projects'):
124
+ shared_projects = group.shared_projects.list(get_all=True)
125
+ self.progress.update_progress_length(len(shared_projects))
126
+ self.add_projects(parent, shared_projects)
122
127
  except GitlabListError as error:
123
128
  log.error(f"Error getting projects on {group.name} id: [{group.id}] error message: [{error.error_message}]")
124
129
 
125
130
  def get_subgroups(self, group, parent):
126
- subgroups = group.subgroups.list(as_list=False, get_all=True)
127
- self.progress.update_progress_length(len(subgroups))
128
- for subgroup_def in subgroups:
129
- try:
130
- subgroup = self.gitlab.groups.get(subgroup_def.id)
131
- subgroup_id = subgroup.name if self.naming == FolderNaming.NAME else subgroup.path
132
- node = self.make_node("subgroup", subgroup_id, parent, url=subgroup.web_url)
133
- self.progress.show_progress(node.name, 'group')
134
- self.get_subgroups(subgroup, node)
135
- self.get_projects(subgroup, node)
136
- except GitlabListError as error:
137
- if error.response_code == 404:
138
- log.error(f"{error.response_code} error while listing subgroup with name: {group.name} [id: {group.id}]. Check your permissions as you may not have access to it. Message: {error.error_message}")
139
- continue
140
- else:
141
- raise error
131
+ try:
132
+ subgroups = group.subgroups.list(as_list=False, get_all=True)
133
+ self.progress.update_progress_length(len(subgroups))
134
+ for subgroup_def in subgroups:
135
+ try:
136
+ subgroup = self.gitlab.groups.get(subgroup_def.id)
137
+ subgroup_id = subgroup.name if self.naming == FolderNaming.NAME else subgroup.path
138
+ node = self.make_node("subgroup", subgroup_id, parent, url=subgroup.web_url)
139
+ self.progress.show_progress(node.name, 'group')
140
+ self.get_subgroups(subgroup, node)
141
+ self.get_projects(subgroup, node)
142
+ except GitlabGetError as error:
143
+ if error.response_code == 404:
144
+ log.error(f"{error.response_code} error while getting subgroup with name: {group.name} [id: {group.id}]. Check your permissions as you may not have access to it. Message: {error.error_message}")
145
+ continue
146
+ else:
147
+ raise error
148
+ except GitlabListError as error:
149
+ if error.response_code == 404:
150
+ log.error(f"{error.response_code} error while listing subgroup with name: {group.name} [id: {group.id}]. Check your permissions as you may not have access to it. Message: {error.error_message}")
151
+ else:
152
+ raise error
142
153
 
143
154
  def load_gitlab_tree(self):
144
155
  log.debug(f"Starting group search with archived: {self.archived} search term: {self.group_search}")
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: gitlabber
3
- Version: 1.2.7
3
+ Version: 1.2.8
4
4
  Summary: A Gitlab clone/pull utility for backing up or cloning Gitlab groups
5
5
  Author-email: Erez Mazor <erezmazor@gmail.com>
6
6
  License: MIT
@@ -34,6 +34,7 @@ Requires-Dist: coverage; extra == "test"
34
34
  Requires-Dist: pytest; extra == "test"
35
35
  Requires-Dist: pytest-cov; extra == "test"
36
36
  Requires-Dist: pytest-integration; extra == "test"
37
+ Dynamic: license-file
37
38
 
38
39
  .. image:: https://github.com/ezbz/gitlabber/actions/workflows/python-app.yml/badge.svg?branch=master
39
40
  :target: https://github.com/ezbz/gitlabber/actions/workflows/python-app.yml
@@ -51,7 +52,7 @@ Requires-Dist: pytest-integration; extra == "test"
51
52
  :target: https://pypi.python.org/pypi/gitlabber/
52
53
 
53
54
  .. image:: https://readthedocs.org/projects/gitlabber/badge/?version=latest&style=plastic
54
- :target: https://gitlabber.readthedocs.io/en/latest/README.html
55
+ :target: https://app.readthedocs.org/projects/gitlabber/
55
56
 
56
57
 
57
58
  Gitlabber
@@ -156,7 +157,6 @@ Usage
156
157
  comma delimited list of glob patterns of paths to projects or groups to exclude from clone/pull
157
158
  -r, --recursive clone/pull git submodules recursively
158
159
  -F, --use-fetch clone/fetch git repository (mirrored repositories)
159
- -d, --dont-checkout don't checkout pulled git repository
160
160
  -s, --include-shared include shared projects in the results
161
161
  -g term, --group-search term
162
162
  only include groups matching the search term, filtering done at the API level (useful for large projects, see: https://docs.gitlab.com/ee/api/groups.html#search-for-group works with partial names of path or name)
@@ -185,7 +185,7 @@ Usage
185
185
  clone projects that start with a case insensitive 'w' using a regular expression:
186
186
  gitlabber -i '/{[w].*}' .
187
187
 
188
- clone a user's personal projects to username-personal-projects
188
+ clone the personal projects to username-personal-projects
189
189
  gitlabber -U .
190
190
 
191
191
  perform a shallow clone of the git repositories
@@ -35,16 +35,4 @@ tests/test_git.py
35
35
  tests/test_gitlab_tree.py
36
36
  tests/test_integration.py
37
37
  tests/test_method.py
38
- tests/test_naming.py
39
- tests/__pycache__/__init__.cpython-311.pyc
40
- tests/__pycache__/gitlab_test_utils.cpython-311.pyc
41
- tests/__pycache__/io_test_util.cpython-311.pyc
42
- tests/__pycache__/test_archive.cpython-311-pytest-8.2.2.pyc
43
- tests/__pycache__/test_cli.cpython-311-pytest-8.2.2.pyc
44
- tests/__pycache__/test_e2e.cpython-311-pytest-8.2.2.pyc
45
- tests/__pycache__/test_format.cpython-311-pytest-8.2.2.pyc
46
- tests/__pycache__/test_git.cpython-311-pytest-8.2.2.pyc
47
- tests/__pycache__/test_gitlab_tree.cpython-311-pytest-8.2.2.pyc
48
- tests/__pycache__/test_integration.cpython-311-pytest-8.2.2.pyc
49
- tests/__pycache__/test_method.cpython-311-pytest-8.2.2.pyc
50
- tests/__pycache__/test_naming.cpython-311-pytest-8.2.2.pyc
38
+ tests/test_naming.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gitlabber"
7
- version = "1.2.7"
7
+ version = "1.2.8"
8
8
  description = "A Gitlab clone/pull utility for backing up or cloning Gitlab groups"
9
9
  readme = "README.rst"
10
10
  requires-python = ">=3"
@@ -54,4 +54,26 @@ gitlabber = "gitlabber.cli:main"
54
54
 
55
55
  [tool.setuptools]
56
56
  packages = ["gitlabber"]
57
- include-package-data = true
57
+ include-package-data = true
58
+
59
+ [tool.pytest.ini_options]
60
+ addopts = [
61
+ "-vv",
62
+ "--cov=gitlabber",
63
+ "--no-cov-on-fail",
64
+ "--cov-append",
65
+ "--cov-report=term-missing",
66
+ "--cov-report=xml",
67
+ "--verbose",
68
+ "--capture=sys",
69
+ "--without-slow-integration",
70
+ "--integration-cover"
71
+ ]
72
+ norecursedirs = [
73
+ "dist",
74
+ "build"
75
+ ]
76
+ testpaths = ["tests"]
77
+
78
+ [tool.coverage.run]
79
+ parallel = true
@@ -0,0 +1,10 @@
1
+ [bdist_wheel]
2
+ universal = 1
3
+
4
+ [metadata]
5
+ description_file = README.rst
6
+
7
+ [egg_info]
8
+ tag_build =
9
+ tag_date = 0
10
+
@@ -0,0 +1,3 @@
1
+ from setuptools import setup
2
+
3
+ setup()
@@ -23,7 +23,7 @@ TREE_TEST_OUTPUT_FILE = "tests/test-output.tree"
23
23
 
24
24
 
25
25
  class MockNode:
26
- def __init__(self, type, id, name, url, subgroups=mock.MagicMock(), projects=mock.MagicMock(), parent_id=None, archived=0, shared=False, group_search=None, git_options=None):
26
+ def __init__(self, type, id, name, url, subgroups=mock.MagicMock(), projects=mock.MagicMock(), shared_projects=mock.MagicMock(), parent_id=None, archived=0, shared=False, group_search=None, git_options=None):
27
27
  self.type = type
28
28
  self.id = id
29
29
  self.name = name
@@ -34,6 +34,7 @@ class MockNode:
34
34
  self.http_url_to_repo = url
35
35
  self.subgroups = subgroups
36
36
  self.projects = projects
37
+ self.shared_projects = shared_projects
37
38
  self.parent_id = parent_id
38
39
  self.archived = archived
39
40
  self.shared = shared
@@ -119,9 +120,17 @@ def validate_tree(root):
119
120
  validate_subgroup(root.children[0].children[0])
120
121
  validate_project(root.children[0].children[0].children[0])
121
122
 
122
- def create_test_gitlab(monkeypatch, includes=None, excludes=None, in_file=None, hide_token=True, method=CloneMethod.SSH):
123
+ def create_test_gitlab(monkeypatch, includes=None, excludes=None, in_file=None, hide_token=True, method=CloneMethod.SSH, token=TOKEN):
123
124
  gl = gitlab_tree.GitlabTree(
124
- URL, TOKEN, "ssh", "name", includes=includes, excludes=excludes, in_file=in_file, hide_token=hide_token)
125
+ URL,
126
+ token,
127
+ method, # Use the method parameter instead of hardcoding "ssh"
128
+ "name",
129
+ includes=includes,
130
+ excludes=excludes,
131
+ in_file=in_file,
132
+ hide_token=hide_token
133
+ )
125
134
  projects = Listable(MockNode("project", 2, PROJECT_NAME, PROJECT_URL if hide_token else PROJECT_URL_WITH_TOKEN))
126
135
  groups = Listable(
127
136
  MockNode("group", 2, GROUP_NAME, GROUP_URL, subgroups=Listable(
@@ -131,7 +140,6 @@ def create_test_gitlab(monkeypatch, includes=None, excludes=None, in_file=None,
131
140
  monkeypatch.setattr(gl.gitlab, "groups", Tree(groups))
132
141
  return gl
133
142
 
134
-
135
143
  def create_test_gitlab_with_toplevel_subgroups(monkeypatch):
136
144
  gl = gitlab_tree.GitlabTree(URL, TOKEN, "ssh", "path")
137
145
  groups = Listable(
@@ -167,9 +175,12 @@ def create_test_gitlab_with_shared(monkeypatch, includes=None, excludes=None, in
167
175
 
168
176
  projects = Listable(
169
177
  MockNode("project", 19, PROJECT_NAME, PROJECT_URL),
178
+ )
179
+
180
+ shared_projects = Listable(
170
181
  MockNode("project", 20, "_shared_" + PROJECT_NAME, "_shared_" + PROJECT_URL, shared=True)
171
182
  )
172
183
  monkeypatch.setattr(gl.gitlab, "groups", Tree(Listable(
173
- MockNode("group", 21, GROUP_NAME, GROUP_URL, projects=projects)
184
+ MockNode("group", 21, GROUP_NAME, GROUP_URL, projects=projects, shared_projects=shared_projects)
174
185
  )))
175
186
  return gl
@@ -11,7 +11,7 @@ coverage.process_startup()
11
11
  @pytest.mark.slow_integration_test
12
12
  def test_clone_subgroup():
13
13
  os.environ['GITLAB_URL'] = 'https://gitlab.com/'
14
- output = io_util.execute(['-p', '--print-format', 'json', '--group-search', 'Group Test'], 60)
14
+ output = io_util.execute(['-p', '--print-format', 'json', '--group-search', 'Group Test'], 90)
15
15
  obj = json.loads(output)
16
16
  assert obj['children'][0]['name'] == 'Group Test'
17
17
  assert obj['children'][0]['children'][0]['name'] == 'Subgroup Test'
@@ -23,7 +23,7 @@ def test_clone_subgroup():
23
23
  @pytest.mark.slow_integration_test
24
24
  def test_clone_subgroup_exclude_archived():
25
25
  os.environ['GITLAB_URL'] = 'https://gitlab.com/'
26
- output = io_util.execute(['-p', '--print-format', 'json', '--group-search', 'Group Test', '-a', 'exclude'], 60)
26
+ output = io_util.execute(['-p', '--print-format', 'json', '--group-search', 'Group Test', '-a', 'exclude'], 90)
27
27
  obj = json.loads(output)
28
28
  assert obj['children'][0]['name'] == 'Group Test'
29
29
  assert obj['children'][0]['children'][0]['name'] == 'Subgroup Test'
@@ -34,7 +34,7 @@ def test_clone_subgroup_exclude_archived():
34
34
  @pytest.mark.slow_integration_test
35
35
  def test_clone_subgroup_only_archived():
36
36
  os.environ['GITLAB_URL'] = 'https://gitlab.com/'
37
- output = io_util.execute(['-p', '--print-format', 'json', '--group-search', 'Group Test', '-a', 'only'], 60)
37
+ output = io_util.execute(['-p', '--print-format', 'json', '--group-search', 'Group Test', '-a', 'only'], 90)
38
38
  obj = json.loads(output)
39
39
  assert obj['children'][0]['name'] == 'Group Test'
40
40
  assert obj['children'][0]['children'][0]['name'] == 'Subgroup Test'
@@ -45,7 +45,7 @@ def test_clone_subgroup_only_archived():
45
45
  @pytest.mark.slow_integration_test
46
46
  def test_clone_subgroup_naming_path():
47
47
  os.environ['GITLAB_URL'] = 'https://gitlab.com/'
48
- output = io_util.execute(['-p', '--print-format', 'json', '-n', 'path', '--group-search', 'Group Test'], 60)
48
+ output = io_util.execute(['-p', '--print-format', 'json', '-n', 'path', '--group-search', 'Group Test'], 90)
49
49
  obj = json.loads(output)
50
50
  assert obj['children'][0]['name'] == 'erez-group-test'
51
51
  assert obj['children'][0]['children'][0]['name'] == 'subgroup-test'
@@ -58,7 +58,7 @@ def test_clone_subgroup_naming_path():
58
58
  @pytest.mark.slow_integration_test
59
59
  def test_large_groups():
60
60
  os.environ['GITLAB_URL'] = 'https://gitlab.com/'
61
- output = io_util.execute(['-p', '--print-format', 'json', '-n', 'path', '--group-search', 'large-group-test'], 60)
61
+ output = io_util.execute(['-p', '--print-format', 'json', '-n', 'path', '--group-search', 'large-group-test'], 90)
62
62
  obj = json.loads(output)
63
63
  assert obj['children'][0]['name'] == 'large-group-test'
64
64
  assert obj['children'][0]['children'][0]['name'] == 'many-subgroups'
@@ -70,8 +70,18 @@ def test_large_groups():
70
70
  @pytest.mark.slow_integration_test
71
71
  def test_user_personal_projects():
72
72
  os.environ['GITLAB_URL'] = 'https://gitlab.com/'
73
- output = io_util.execute(['-p', '--print-format', 'json', '-n', 'path', '--user-projects'], 60)
73
+ output = io_util.execute(['-p', '--print-format', 'json', '-n', 'path', '--user-projects'], 90)
74
74
  obj = json.loads(output)
75
75
  assert obj['children'][0]['name'] == 'erezmazor-prsonal-projects'
76
76
  assert obj['children'][0]['children'][0]['name'] == 'gitlabber-personal-project'
77
+
78
+
79
+ @pytest.mark.slow_integration_test
80
+ def test_shared_group_and_project():
81
+ os.environ['GITLAB_URL'] = 'https://gitlab.com/'
82
+ output = io_util.execute(['-p', '--print-format', 'json', '-s', '--group-search', 'shared-group3'], 90)
83
+ obj = json.loads(output)
84
+ assert obj['children'][0]['name'] == 'Shared Group'
85
+ assert obj['children'][0]['children'][0]['name'] == 'Shared Project'
86
+
77
87
 
@@ -1,8 +1,10 @@
1
-
2
1
  from gitlabber.method import CloneMethod
3
2
  import tests.gitlab_test_utils as gitlab_util
4
3
  import tests.io_test_util as output_util
5
4
  from gitlabber.archive import ArchivedResults
5
+ import pytest
6
+ from unittest import mock
7
+ from gitlab.exceptions import GitlabGetError
6
8
 
7
9
  def test_load_tree(monkeypatch):
8
10
  gl = gitlab_util.create_test_gitlab(monkeypatch)
@@ -173,3 +175,73 @@ def test_hide_token_from_project_url(monkeypatch):
173
175
  gl.load_tree()
174
176
  gl.print_tree()
175
177
  assert 'gitlab-token:xxx@' not in gl.root.children[0].children[0].children[0].url
178
+
179
+
180
+ def test_get_subgroups_404_error(monkeypatch):
181
+ gl = gitlab_util.create_test_gitlab(monkeypatch)
182
+
183
+ # Create mock group and subgroup
184
+ mock_group = mock.Mock()
185
+ mock_group.name = "mock_group"
186
+ mock_group.id = 123
187
+
188
+ # Create a mock subgroup definition that will be returned by list()
189
+ mock_subgroup_def = mock.Mock()
190
+ mock_subgroup_def.id = 456
191
+
192
+ # Make subgroups.list return our mock subgroup definition
193
+ mock_group.subgroups.list.return_value = [mock_subgroup_def]
194
+
195
+ # This is the function that will raise the 404 when trying to get the subgroup
196
+ def mock_get_subgroup(id):
197
+ raise GitlabGetError(response_code=404, error_message="Not Found")
198
+
199
+ # Patch the groups.get method
200
+ monkeypatch.setattr(gl.gitlab.groups, "get", mock_get_subgroup)
201
+
202
+ with mock.patch("gitlabber.gitlab_tree.log.error") as mock_log_error:
203
+ gl.get_subgroups(mock_group, gl.root)
204
+
205
+ mock_log_error.assert_called_once_with(
206
+ f"404 error while getting subgroup with name: {mock_group.name} [id: {mock_group.id}]. Check your permissions as you may not have access to it. Message: Not Found"
207
+ )
208
+
209
+ def test_hide_token_in_project_url_both_cases(monkeypatch):
210
+ test_token = "test-token-123"
211
+
212
+ # Create two instances to test both cases
213
+ gl_hidden = gitlab_util.create_test_gitlab(monkeypatch,
214
+ hide_token=True,
215
+ method=CloneMethod.HTTP,
216
+ token=test_token)
217
+
218
+ gl_visible = gitlab_util.create_test_gitlab(monkeypatch,
219
+ hide_token=False,
220
+ method=CloneMethod.HTTP,
221
+ token=test_token)
222
+
223
+ # Create mock project
224
+ mock_project = mock.Mock()
225
+ mock_project.name = "test-project"
226
+ mock_project.path = "test-project"
227
+ mock_project.ssh_url_to_repo = "git@gitlab.com:group/test-project.git"
228
+ mock_project.http_url_to_repo = "https://gitlab.com/group/test-project.git"
229
+
230
+ # Test with hide_token=True
231
+ with mock.patch("gitlabber.gitlab_tree.log.debug") as mock_log_debug_hidden:
232
+ gl_hidden.add_projects(gl_hidden.root, [mock_project])
233
+ project_node_hidden = gl_hidden.root.children[0]
234
+
235
+ # Verify token is not in URL
236
+ assert project_node_hidden.url == "https://gitlab.com/group/test-project.git"
237
+ mock_log_debug_hidden.assert_any_call("Hiding token from project url: %s",
238
+ project_node_hidden.url)
239
+
240
+ # Test with hide_token=False
241
+ with mock.patch("gitlabber.gitlab_tree.log.debug") as mock_log_debug_visible:
242
+ gl_visible.add_projects(gl_visible.root, [mock_project])
243
+ project_node_visible = gl_visible.root.children[0]
244
+
245
+ expected_url = f"https://gitlab-token:{test_token}@gitlab.com/group/test-project.git"
246
+ assert project_node_visible.url == expected_url
247
+ mock_log_debug_visible.assert_any_call("Generated URL: %s", expected_url)
@@ -1,2 +0,0 @@
1
- """ Gitlabber """
2
- __version__ = '1.2.7'
gitlabber-1.2.7/setup.cfg DELETED
@@ -1,24 +0,0 @@
1
- [bdist_wheel]
2
- universal = 1
3
-
4
- [metadata]
5
- description_file = README.rst
6
-
7
- [coverage:run]
8
- parallel = true
9
-
10
- [tool:pytest]
11
- addopts =
12
- -vv --cov=gitlabber --no-cov-on-fail --cov-append --cov-report term-missing --cov-report xml --verbose --capture=sys --without-slow-integration --integration-cover
13
- norecursedirs =
14
- dist
15
- build
16
-
17
- [aliases]
18
- dists = sdist bdist_wheel
19
- testpaths = tests
20
-
21
- [egg_info]
22
- tag_build =
23
- tag_date = 0
24
-
gitlabber-1.2.7/setup.py DELETED
@@ -1,90 +0,0 @@
1
- from setuptools import setup
2
-
3
- setup()
4
-
5
-
6
- # """Packaging settings."""
7
-
8
-
9
- # from codecs import open
10
- # from os.path import abspath, dirname, join
11
- # from subprocess import call
12
-
13
- # from setuptools import Command, find_packages, setup
14
-
15
- # this_dir = abspath(dirname(__file__))
16
- # with open(join(this_dir, 'README.rst'), encoding='utf-8') as file:
17
- # long_description = file.read()
18
-
19
-
20
- # class RunTests(Command):
21
- # """Run all tests."""
22
- # description = 'run tests'
23
- # user_options = []
24
-
25
- # def initialize_options(self):
26
- # pass
27
-
28
- # def finalize_options(self):
29
- # pass
30
-
31
- # def run(self):
32
- # """Run all tests!"""
33
- # errno = call(['py.test'])
34
- # raise SystemExit(errno)
35
- # setup(
36
- # python_requires='>=3',
37
- # name = 'gitlabber',
38
- # packages = find_packages(include=['gitlabber']),
39
- # version = '1.2.7',
40
- # description = 'A Gitlab clone/pull utility for backing up or cloning Gitlab groups',
41
- # long_description = long_description,
42
- # long_description_content_type="text/x-rst",
43
- # url = 'https://github.com/ezbz/gitlabber',
44
- # download_url = 'https://github.com/ezbz/gitlabber/archive/main.zip',
45
- # author = 'Erez Mazor',
46
- # author_email = 'erezmazor@gmail.com',
47
- # license = 'MIT',
48
- # keywords = ['gitlab', 'python', 'cli'],
49
- # include_package_data = True,
50
-
51
- # classifiers = [
52
- # 'Development Status :: 4 - Beta',
53
- # 'Intended Audience :: Developers',
54
- # 'Topic :: Utilities',
55
- # 'License :: OSI Approved :: MIT License',
56
- # 'Natural Language :: English',
57
- # 'Operating System :: OS Independent',
58
- # 'Programming Language :: Python :: 3',
59
- # 'Programming Language :: Python :: 3.9',
60
- # 'Programming Language :: Python :: 3.10',
61
- # 'Programming Language :: Python :: 3.11',
62
- # 'Programming Language :: Python :: 3.12',
63
- # 'Programming Language :: Python :: 3.13'
64
- # ],
65
- # setup_requires = [
66
- # 'docopt',
67
- # 'anytree',
68
- # 'globre',
69
- # 'pyyaml',
70
- # 'tqdm',
71
- # 'GitPython',
72
- # 'python-gitlab'
73
- # ],
74
- # install_requires = [
75
- # 'docopt',
76
- # 'anytree',
77
- # 'globre',
78
- # 'pyyaml',
79
- # 'tqdm',
80
- # 'GitPython',
81
- # 'python-gitlab'
82
- # ],
83
- # tests_require= ['coverage', 'pytest', 'pytest-cov', 'pytest-integration'],
84
- # entry_points = {
85
- # 'console_scripts': [
86
- # 'gitlabber=gitlabber.cli:main',
87
- # ],
88
- # },
89
- # cmdclass = {'test': RunTests},
90
- # )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes