cgitize 8.0.1__tar.gz → 8.0.2__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 (75) hide show
  1. cgitize-8.0.2/.git-blame-ignore-revs +1 -0
  2. {cgitize-8.0.1 → cgitize-8.0.2}/PKG-INFO +1 -1
  3. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/bitbucket.py +2 -2
  4. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/cgit.py +23 -23
  5. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/config.py +35 -35
  6. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/git.py +32 -32
  7. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/github.py +2 -2
  8. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/gitlab.py +1 -1
  9. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/header.py +6 -6
  10. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/main.py +11 -11
  11. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/repo.py +29 -29
  12. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/utils.py +17 -15
  13. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/version.py +2 -2
  14. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/PKG-INFO +1 -1
  15. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/SOURCES.txt +1 -0
  16. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/scm_file_list.json +1 -0
  17. cgitize-8.0.2/cgitize.egg-info/scm_version.json +8 -0
  18. {cgitize-8.0.1 → cgitize-8.0.2}/docker/get_output_dir.py +2 -2
  19. {cgitize-8.0.1 → cgitize-8.0.2}/pyproject.toml +0 -3
  20. {cgitize-8.0.1 → cgitize-8.0.2}/requirements.txt +1 -1
  21. cgitize-8.0.2/test/unit/test_bitbucket.py +99 -0
  22. cgitize-8.0.2/test/unit/test_github.py +62 -0
  23. cgitize-8.0.2/test/unit/test_gitlab.py +65 -0
  24. cgitize-8.0.1/cgitize.egg-info/scm_version.json +0 -8
  25. cgitize-8.0.1/test/unit/test_bitbucket.py +0 -99
  26. cgitize-8.0.1/test/unit/test_github.py +0 -62
  27. cgitize-8.0.1/test/unit/test_gitlab.py +0 -65
  28. {cgitize-8.0.1 → cgitize-8.0.2}/.dockerignore +0 -0
  29. {cgitize-8.0.1 → cgitize-8.0.2}/.gitattributes +0 -0
  30. {cgitize-8.0.1 → cgitize-8.0.2}/.github/dependabot.yml +0 -0
  31. {cgitize-8.0.1 → cgitize-8.0.2}/.github/workflows/ci.yml +0 -0
  32. {cgitize-8.0.1 → cgitize-8.0.2}/.github/workflows/maintenance.yml +0 -0
  33. {cgitize-8.0.1 → cgitize-8.0.2}/.gitignore +0 -0
  34. {cgitize-8.0.1 → cgitize-8.0.2}/.pylintrc +0 -0
  35. {cgitize-8.0.1 → cgitize-8.0.2}/.python-version +0 -0
  36. {cgitize-8.0.1 → cgitize-8.0.2}/DEVELOPMENT.md +0 -0
  37. {cgitize-8.0.1 → cgitize-8.0.2}/LICENSE.txt +0 -0
  38. {cgitize-8.0.1 → cgitize-8.0.2}/Makefile +0 -0
  39. {cgitize-8.0.1 → cgitize-8.0.2}/README.md +0 -0
  40. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize/__init__.py +0 -0
  41. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/dependency_links.txt +0 -0
  42. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/entry_points.txt +0 -0
  43. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/requires.txt +0 -0
  44. {cgitize-8.0.1 → cgitize-8.0.2}/cgitize.egg-info/top_level.txt +0 -0
  45. {cgitize-8.0.1 → cgitize-8.0.2}/docker/Dockerfile +0 -0
  46. {cgitize-8.0.1 → cgitize-8.0.2}/docker/README.md +0 -0
  47. {cgitize-8.0.1 → cgitize-8.0.2}/docker/cgitize.sh +0 -0
  48. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/Dockerfile +0 -0
  49. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/cmd.sh +0 -0
  50. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/etc/cgit/common +0 -0
  51. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/etc/cgitrc +0 -0
  52. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/etc/nginx/conf.d/default.conf +0 -0
  53. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/usr/lib/cgit/filters/about-formatting.sh +0 -0
  54. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/usr/lib/cgit/filters/html-converters/.gitattributes +0 -0
  55. {cgitize-8.0.1 → cgitize-8.0.2}/docker/frontend/usr/lib/cgit/filters/html-converters/md2html +0 -0
  56. {cgitize-8.0.1 → cgitize-8.0.2}/docker/in_cron.sh +0 -0
  57. {cgitize-8.0.1 → cgitize-8.0.2}/docker-compose.yml +0 -0
  58. {cgitize-8.0.1 → cgitize-8.0.2}/docs/api.md +0 -0
  59. {cgitize-8.0.1 → cgitize-8.0.2}/docs/auth.md +0 -0
  60. {cgitize-8.0.1 → cgitize-8.0.2}/examples/cgitize.toml +0 -0
  61. {cgitize-8.0.1 → cgitize-8.0.2}/examples/docker/cgitize.toml +0 -0
  62. {cgitize-8.0.1 → cgitize-8.0.2}/prelude.mk +0 -0
  63. {cgitize-8.0.1 → cgitize-8.0.2}/setup.cfg +0 -0
  64. {cgitize-8.0.1 → cgitize-8.0.2}/test/__init__.py +0 -0
  65. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/.dockerignore +0 -0
  66. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/cgitize/.gitignore +0 -0
  67. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/cgitize/etc/cgitize.toml +0 -0
  68. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/docker-compose.yml +0 -0
  69. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/git_server/Dockerfile +0 -0
  70. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/git_server/setup_repo.sh +0 -0
  71. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/docker/test.sh +0 -0
  72. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/example/test.sh +0 -0
  73. {cgitize-8.0.1 → cgitize-8.0.2}/test/integration/local/test.sh +0 -0
  74. {cgitize-8.0.1 → cgitize-8.0.2}/test/set_credentials.sh +0 -0
  75. {cgitize-8.0.1 → cgitize-8.0.2}/test/unit/__init__.py +0 -0
@@ -0,0 +1 @@
1
+ ebbab9207fc3ec5dcf2df9011d945a8de2617983
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cgitize
3
- Version: 8.0.1
3
+ Version: 8.0.2
4
4
  Summary: Self-host your repositories using cgit
5
5
  Author-email: Egor Tensin <egor@tensin.name>
6
6
  License-Expression: MIT
@@ -17,10 +17,10 @@ class Bitbucket:
17
17
 
18
18
  def get_repo(self, repo):
19
19
  try:
20
- parts = repo.id.split('/')
20
+ parts = repo.id.split("/")
21
21
  if len(parts) != 2:
22
22
  raise ValueError(
23
- f'repository ID must be in the USER/NAME format: {repo.id}'
23
+ f"repository ID must be in the USER/NAME format: {repo.id}"
24
24
  )
25
25
  user, name = parts
26
26
  return self._impl.repositories.get(user, name)
@@ -27,20 +27,20 @@ class CGitRCWriter:
27
27
 
28
28
  @staticmethod
29
29
  def get_path(repo_dir):
30
- return os.path.join(repo_dir, 'cgitrc')
30
+ return os.path.join(repo_dir, "cgitrc")
31
31
 
32
32
  def write(self, repo_dir, repo):
33
- with open(self.get_path(repo_dir), 'w') as fd:
34
- self._write_field(fd, 'clone-url', self._build_clone_url(repo))
35
- self._write_field(fd, 'owner', repo.owner)
36
- self._write_field(fd, 'desc', repo.desc)
37
- self._write_field(fd, 'homepage', repo.homepage)
33
+ with open(self.get_path(repo_dir), "w") as fd:
34
+ self._write_field(fd, "clone-url", self._build_clone_url(repo))
35
+ self._write_field(fd, "owner", repo.owner)
36
+ self._write_field(fd, "desc", repo.desc)
37
+ self._write_field(fd, "homepage", repo.homepage)
38
38
 
39
39
  @staticmethod
40
40
  def _write_field(fd, field, value):
41
41
  if value is None:
42
42
  return
43
- fd.write(f'{field}={value}\n')
43
+ fd.write(f"{field}={value}\n")
44
44
 
45
45
  def _build_clone_url(self, repo):
46
46
  clone_urls = []
@@ -51,7 +51,7 @@ class CGitRCWriter:
51
51
  clone_urls.append(repo.clone_url)
52
52
  if not clone_urls:
53
53
  return None
54
- clone_urls = ' '.join(clone_urls)
54
+ clone_urls = " ".join(clone_urls)
55
55
  return clone_urls
56
56
 
57
57
 
@@ -61,8 +61,8 @@ class AgeFile:
61
61
  timestamp = AgeFile.get_age(repo_dir)
62
62
  if timestamp:
63
63
  os.makedirs(AgeFile.get_dir(repo_dir), exist_ok=True)
64
- with open(AgeFile.get_path(repo_dir), mode='w') as fd:
65
- fd.write(f'{timestamp}')
64
+ with open(AgeFile.get_path(repo_dir), mode="w") as fd:
65
+ fd.write(f"{timestamp}")
66
66
 
67
67
  @staticmethod
68
68
  def get_age(repo_dir):
@@ -71,10 +71,10 @@ class AgeFile:
71
71
  # represents activity.
72
72
  with chdir(repo_dir):
73
73
  success, output = Git.capture(
74
- 'for-each-ref',
75
- '--sort=-committerdate',
76
- '--count=1',
77
- '--format=%(committerdate:iso8601)',
74
+ "for-each-ref",
75
+ "--sort=-committerdate",
76
+ "--count=1",
77
+ "--format=%(committerdate:iso8601)",
78
78
  )
79
79
  if not success:
80
80
  logging.error(
@@ -86,11 +86,11 @@ class AgeFile:
86
86
 
87
87
  @staticmethod
88
88
  def get_dir(repo_dir):
89
- return os.path.join(repo_dir, 'info', 'web')
89
+ return os.path.join(repo_dir, "info", "web")
90
90
 
91
91
  @staticmethod
92
92
  def get_path(repo_dir):
93
- return os.path.join(AgeFile.get_dir(repo_dir), 'last-modified')
93
+ return os.path.join(AgeFile.get_dir(repo_dir), "last-modified")
94
94
 
95
95
 
96
96
  class CGitRepositories:
@@ -123,16 +123,16 @@ class CGitRepositories:
123
123
  return self._mirror(repo)
124
124
 
125
125
  with chdir(repo_dir):
126
- success, output = Git.capture('rev-parse', '--is-inside-work-tree')
126
+ success, output = Git.capture("rev-parse", "--is-inside-work-tree")
127
127
  if not success:
128
128
  # Overwrite the existing directory if it's not a Git repository.
129
129
  logging.warning(
130
- 'Local directory is not a repository, going to overwrite it: %s',
130
+ "Local directory is not a repository, going to overwrite it: %s",
131
131
  repo_dir,
132
132
  )
133
133
  return self._mirror(repo)
134
134
 
135
- success, output = Git.capture('config', '--get', 'remote.origin.url')
135
+ success, output = Git.capture("config", "--get", "remote.origin.url")
136
136
  if not success:
137
137
  # Every repository managed by this script should have the
138
138
  # 'origin' remote. If it doesn't, it's trash. Overwrite the
@@ -143,7 +143,7 @@ class CGitRepositories:
143
143
  )
144
144
  return self._mirror(repo)
145
145
 
146
- if f'{repo.clone_url}\n' != output:
146
+ if f"{repo.clone_url}" != output:
147
147
  # Jeez, there's a proper local repository in the target
148
148
  # directory already with a different upstream; something's
149
149
  # wrong, fix it manually.
@@ -172,16 +172,16 @@ class CGitRepositories:
172
172
  logging.exception(e)
173
173
  return False
174
174
  with Git.setup_auth(repo):
175
- return Git.check('clone', '--mirror', '--quiet', repo.clone_url, repo_dir)
175
+ return Git.check("clone", "--mirror", "--quiet", repo.clone_url, repo_dir)
176
176
 
177
177
  def _fix_upstream_url(self, repo):
178
178
  repo_dir = self.get_repo_dir(repo)
179
179
  with chdir(repo_dir):
180
- return Git.check('remote', 'set-url', 'origin', repo.clone_url)
180
+ return Git.check("remote", "set-url", "origin", repo.clone_url)
181
181
 
182
182
  def _update_existing(self, repo):
183
183
  logging.info("Updating repository '%s'", repo.name)
184
184
  repo_dir = self.get_repo_dir(repo)
185
185
  with chdir(repo_dir):
186
186
  with Git.setup_auth(repo):
187
- return Git.check('remote', 'update', '--prune')
187
+ return Git.check("remote", "update", "--prune")
@@ -22,7 +22,7 @@ class Section:
22
22
  def _get_config_value(self, key, required=True, default=None):
23
23
  if required and default is None:
24
24
  if not key in self.impl:
25
- raise RuntimeError(f'configuration value is missing: {key}')
25
+ raise RuntimeError(f"configuration value is missing: {key}")
26
26
  return self.impl.get(key, default)
27
27
 
28
28
  def _get_config_path(self, *args, **kwargs):
@@ -38,36 +38,36 @@ class Section:
38
38
 
39
39
 
40
40
  class MainSection(Section):
41
- DEFAULT_OUTPUT_DIR = '/mnt/cgitize'
41
+ DEFAULT_OUTPUT_DIR = "/mnt/cgitize"
42
42
 
43
43
  @property
44
44
  def output_dir(self):
45
45
  return self._get_config_path(
46
- 'output_dir', default=MainSection.DEFAULT_OUTPUT_DIR
46
+ "output_dir", default=MainSection.DEFAULT_OUTPUT_DIR
47
47
  )
48
48
 
49
49
  @property
50
50
  def error_header_path(self):
51
- return os.path.join(self.output_dir, 'error.html')
51
+ return os.path.join(self.output_dir, "error.html")
52
52
 
53
53
  @property
54
54
  def clone_url(self):
55
- return self._get_config_value('clone_url', required=False)
55
+ return self._get_config_value("clone_url", required=False)
56
56
 
57
57
  @property
58
58
  def clone_via_ssh(self):
59
- return self._get_config_value('clone_via_ssh', default=True)
59
+ return self._get_config_value("clone_via_ssh", default=True)
60
60
 
61
61
  @property
62
62
  def default_owner(self):
63
- return self._get_config_value('owner', required=False)
63
+ return self._get_config_value("owner", required=False)
64
64
 
65
65
 
66
66
  class ServiceSection(Section, ABC):
67
67
  def __init__(self, impl):
68
68
  super().__init__(impl)
69
- self.repositories = RepositoriesSection(self.impl.get('repositories', {}))
70
- self.users = UsersSection(self.impl.get('users', {}))
69
+ self.repositories = RepositoriesSection(self.impl.get("repositories", {}))
70
+ self.users = UsersSection(self.impl.get("users", {}))
71
71
 
72
72
  def _enum_explicit_repositories(self, cfg, api):
73
73
  for r in self.repositories.enum_repositories():
@@ -99,15 +99,15 @@ class ServiceSection(Section, ABC):
99
99
  class GitHubSection(ServiceSection):
100
100
  def __init__(self, impl):
101
101
  super().__init__(impl)
102
- self.orgs = OrgsSection(self.impl.get('organizations', {}))
102
+ self.orgs = OrgsSection(self.impl.get("organizations", {}))
103
103
 
104
104
  @property
105
105
  def token(self):
106
- return self._get_config_or_env('token', 'CGITIZE_GITHUB_TOKEN')
106
+ return self._get_config_or_env("token", "CGITIZE_GITHUB_TOKEN")
107
107
 
108
108
  @property
109
109
  def username(self):
110
- return self._get_config_or_env('username', 'CGITIZE_GITHUB_USERNAME')
110
+ return self._get_config_or_env("username", "CGITIZE_GITHUB_USERNAME")
111
111
 
112
112
  @property
113
113
  def url_auth(self):
@@ -131,7 +131,7 @@ class GitHubSection(ServiceSection):
131
131
  token = self.token
132
132
  if (username is None) != (token is None):
133
133
  raise RuntimeError(
134
- 'please set either both the GitHub username & token, or neither'
134
+ "please set either both the GitHub username & token, or neither"
135
135
  )
136
136
  return GitHub(username, token)
137
137
 
@@ -139,11 +139,11 @@ class GitHubSection(ServiceSection):
139
139
  class BitbucketSection(ServiceSection):
140
140
  @property
141
141
  def token(self):
142
- return self._get_config_or_env('token', 'CGITIZE_BITBUCKET_TOKEN')
142
+ return self._get_config_or_env("token", "CGITIZE_BITBUCKET_TOKEN")
143
143
 
144
144
  @property
145
145
  def username(self):
146
- return self._get_config_or_env('email', 'CGITIZE_BITBUCKET_EMAIL')
146
+ return self._get_config_or_env("email", "CGITIZE_BITBUCKET_EMAIL")
147
147
 
148
148
  @property
149
149
  def url_auth(self):
@@ -154,7 +154,7 @@ class BitbucketSection(ServiceSection):
154
154
  token = self.token
155
155
  if (username is None) != (token is None):
156
156
  raise RuntimeError(
157
- 'please set either both the Bitbucket username & token, or neither'
157
+ "please set either both the Bitbucket username & token, or neither"
158
158
  )
159
159
  return Bitbucket(username, token)
160
160
 
@@ -162,11 +162,11 @@ class BitbucketSection(ServiceSection):
162
162
  class GitLabSection(ServiceSection):
163
163
  @property
164
164
  def token(self):
165
- return self._get_config_or_env('token', 'CGITIZE_GITLAB_TOKEN')
165
+ return self._get_config_or_env("token", "CGITIZE_GITLAB_TOKEN")
166
166
 
167
167
  @property
168
168
  def username(self):
169
- return self._get_config_or_env('username', 'CGITIZE_GITLAB_USERNAME')
169
+ return self._get_config_or_env("username", "CGITIZE_GITLAB_USERNAME")
170
170
 
171
171
  @property
172
172
  def url_auth(self):
@@ -177,7 +177,7 @@ class GitLabSection(ServiceSection):
177
177
  token = self.token
178
178
  if (username is None) != (token is None):
179
179
  raise RuntimeError(
180
- 'please set either both the GitLab username & token, or neither'
180
+ "please set either both the GitLab username & token, or neither"
181
181
  )
182
182
  return GitLab(token)
183
183
 
@@ -200,56 +200,56 @@ class RepositoriesSection(Section):
200
200
  class Entity(ABC):
201
201
  @property
202
202
  def name(self):
203
- return self._impl['name']
203
+ return self._impl["name"]
204
204
 
205
205
  @property
206
206
  def dir(self):
207
- return self._impl.get('dir')
207
+ return self._impl.get("dir")
208
208
 
209
209
  @property
210
210
  def skip(self):
211
- return self._impl.get('skip', [])
211
+ return self._impl.get("skip", [])
212
212
 
213
213
 
214
214
  class User(Entity):
215
215
  def __init__(self, impl):
216
- if 'name' not in impl:
216
+ if "name" not in impl:
217
217
  raise ValueError("every user must have a 'name'")
218
218
  self._impl = impl
219
219
 
220
220
  @property
221
221
  def public_repos(self):
222
- return self._impl.get('public', True)
222
+ return self._impl.get("public", True)
223
223
 
224
224
  @property
225
225
  def private_repos(self):
226
- return self._impl.get('private', False)
226
+ return self._impl.get("private", False)
227
227
 
228
228
 
229
229
  class Org(Entity):
230
230
  def __init__(self, impl):
231
- if 'name' not in impl:
231
+ if "name" not in impl:
232
232
  raise ValueError("every organization must have a 'name'")
233
233
  self._impl = impl
234
234
 
235
235
 
236
236
  class HostedRepo:
237
237
  def __init__(self, impl):
238
- if 'id' not in impl:
238
+ if "id" not in impl:
239
239
  raise ValueError("every hosted repository must have 'id'")
240
240
  self._impl = impl
241
241
 
242
242
  @property
243
243
  def id(self):
244
- return self._impl['id']
244
+ return self._impl["id"]
245
245
 
246
246
  @property
247
247
  def dir(self):
248
- return self._impl.get('dir')
248
+ return self._impl.get("dir")
249
249
 
250
250
 
251
251
  class Config:
252
- DEFAULT_PATH = '/etc/cgitize/cgitize.toml'
252
+ DEFAULT_PATH = "/etc/cgitize/cgitize.toml"
253
253
 
254
254
  @staticmethod
255
255
  def read(path):
@@ -257,13 +257,13 @@ class Config:
257
257
 
258
258
  def __init__(self, path):
259
259
  self.path = os.path.abspath(path)
260
- with open(self.path, 'rb') as f:
260
+ with open(self.path, "rb") as f:
261
261
  self.impl = tomli.load(f)
262
262
  self.main = MainSection(self.impl)
263
- self.repositories = RepositoriesSection(self.impl.get('repositories', {}))
264
- self.github = GitHubSection(self.impl.get('github', {}))
265
- self.bitbucket = BitbucketSection(self.impl.get('bitbucket', {}))
266
- self.gitlab = GitLabSection(self.impl.get('gitlab', {}))
263
+ self.repositories = RepositoriesSection(self.impl.get("repositories", {}))
264
+ self.github = GitHubSection(self.impl.get("github", {}))
265
+ self.bitbucket = BitbucketSection(self.impl.get("bitbucket", {}))
266
+ self.gitlab = GitLabSection(self.impl.get("gitlab", {}))
267
267
 
268
268
  def _parse_explicit_repositories(self):
269
269
  for r in self.repositories.enum_repositories():
@@ -9,8 +9,8 @@ import os
9
9
  from cgitize import utils
10
10
 
11
11
  GIT_ENV = os.environ.copy()
12
- GIT_ENV['GIT_SSH_COMMAND'] = (
13
- 'ssh -oBatchMode=yes -oLogLevel=QUIET -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null'
12
+ GIT_ENV["GIT_SSH_COMMAND"] = (
13
+ "ssh -oBatchMode=yes -oLogLevel=QUIET -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null"
14
14
  )
15
15
 
16
16
 
@@ -21,15 +21,15 @@ class Config:
21
21
  def exists(self):
22
22
  return os.path.exists(self.path)
23
23
 
24
- def open(self, mode='r'):
25
- return open(self.path, mode=mode, encoding='utf-8')
24
+ def open(self, mode="r"):
25
+ return open(self.path, mode=mode, encoding="utf-8")
26
26
 
27
27
  def read(self):
28
- with self.open(mode='r') as fd:
28
+ with self.open(mode="r") as fd:
29
29
  return fd.read()
30
30
 
31
31
  def write(self, contents):
32
- with self.open(mode='w') as fd:
32
+ with self.open(mode="w") as fd:
33
33
  fd.write(contents)
34
34
 
35
35
  @contextmanager
@@ -52,12 +52,12 @@ class Config:
52
52
  @staticmethod
53
53
  def validate_name(name):
54
54
  if not name:
55
- raise RuntimeError('section names cannot be empty')
55
+ raise RuntimeError("section names cannot be empty")
56
56
  for c in name:
57
- if c.isalnum() or c == '-' or c == '.':
57
+ if c.isalnum() or c == "-" or c == ".":
58
58
  continue
59
59
  raise RuntimeError(
60
- f'section names must only contain alphanumeric characters, . or -: {name}'
60
+ f"section names must only contain alphanumeric characters, . or -: {name}"
61
61
  )
62
62
 
63
63
  @staticmethod
@@ -65,8 +65,8 @@ class Config:
65
65
  return name
66
66
 
67
67
  def format(self):
68
- result = f'[{self.format_name(self.name)}]\n'
69
- result += ''.join((var.format() for var in self.variables))
68
+ result = f"[{self.format_name(self.name)}]\n"
69
+ result += "".join((var.format() for var in self.variables))
70
70
  return result
71
71
 
72
72
  class Subsection:
@@ -79,23 +79,23 @@ class Config:
79
79
 
80
80
  @staticmethod
81
81
  def validate_name(name):
82
- if '\n' in name:
83
- raise RuntimeError(f'subsection names cannot contain newlines: {name}')
82
+ if "\n" in name:
83
+ raise RuntimeError(f"subsection names cannot contain newlines: {name}")
84
84
 
85
85
  def format_name(self):
86
86
  name = self.name
87
87
  # Escape the backslashes:
88
- name = name.replace('\\', r'\\')
88
+ name = name.replace("\\", r"\\")
89
89
  # Escape the quotes:
90
- name = name.replace('"', r'\"')
90
+ name = name.replace('"', r"\"")
91
91
  # Put in quotes:
92
92
  return f'"{name}"'
93
93
 
94
94
  def format(self):
95
95
  result = (
96
- f'[{Config.Section.format_name(self.section)} {self.format_name()}]\n'
96
+ f"[{Config.Section.format_name(self.section)} {self.format_name()}]\n"
97
97
  )
98
- result += ''.join((var.format() for var in self.variables))
98
+ result += "".join((var.format() for var in self.variables))
99
99
  return result
100
100
 
101
101
  class Variable:
@@ -108,16 +108,16 @@ class Config:
108
108
  @staticmethod
109
109
  def validate_name(name):
110
110
  if not name:
111
- raise RuntimeError('variable names cannot be empty')
111
+ raise RuntimeError("variable names cannot be empty")
112
112
  for c in name:
113
- if c.isalnum() or c == '-':
113
+ if c.isalnum() or c == "-":
114
114
  continue
115
115
  raise RuntimeError(
116
- f'variable name can only contain alphanumeric characters or -: {name}'
116
+ f"variable name can only contain alphanumeric characters or -: {name}"
117
117
  )
118
118
  if not name[0].isalnum():
119
119
  raise RuntimeError(
120
- f'variable name must start with an alphanumeric character: {name}'
120
+ f"variable name must start with an alphanumeric character: {name}"
121
121
  )
122
122
 
123
123
  @staticmethod
@@ -130,23 +130,23 @@ class Config:
130
130
  def format_value(self):
131
131
  value = self.value
132
132
  # Escape the backslashes:
133
- value = value.replace('\\', r'\\')
133
+ value = value.replace("\\", r"\\")
134
134
  # Escape the supported escape sequences (\n, \t and \b):
135
- value = value.replace('\n', r'\n')
136
- value = value.replace('\t', r'\t')
137
- value = value.replace('\b', r'\b')
135
+ value = value.replace("\n", r"\n")
136
+ value = value.replace("\t", r"\t")
137
+ value = value.replace("\b", r"\b")
138
138
  # Escape the quotes:
139
- value = value.replace('"', r'\"')
139
+ value = value.replace('"', r"\"")
140
140
  # Put in quotes:
141
141
  value = f'"{value}"'
142
142
  return value
143
143
 
144
144
  def format(self):
145
- return f' {self.format_name()} = {self.format_value()}\n'
145
+ return f" {self.format_name()} = {self.format_value()}\n"
146
146
 
147
147
 
148
148
  class Git:
149
- EXE = 'git'
149
+ EXE = "git"
150
150
 
151
151
  @staticmethod
152
152
  def check(*args, **kwargs):
@@ -158,7 +158,7 @@ class Git:
158
158
 
159
159
  @staticmethod
160
160
  def get_global_config():
161
- return Config(os.path.expanduser('~/.gitconfig'))
161
+ return Config(os.path.expanduser("~/.gitconfig"))
162
162
 
163
163
  @staticmethod
164
164
  @contextmanager
@@ -169,10 +169,10 @@ class Git:
169
169
  config = Git.get_global_config()
170
170
  with utils.protected_file(config.path):
171
171
  with config.backup() as old_contents:
172
- variables = [Config.Variable('insteadOf', repo.clone_url)]
172
+ variables = [Config.Variable("insteadOf", repo.clone_url)]
173
173
  subsection = Config.Subsection(
174
- 'url', repo.clone_url_with_auth, variables
174
+ "url", repo.clone_url_with_auth, variables
175
175
  )
176
- new_contents = f'{old_contents}\n{subsection.format()}'
176
+ new_contents = f"{old_contents}\n{subsection.format()}"
177
177
  config.write(new_contents)
178
178
  yield
@@ -34,13 +34,13 @@ class GitHub:
34
34
  # None makes no difference.
35
35
  kwargs = {}
36
36
  if visibility is not None:
37
- kwargs['visibility'] = visibility
37
+ kwargs["visibility"] = visibility
38
38
 
39
39
  try:
40
40
  if user.name == self._username:
41
41
  # To get private repositories, get_user() must be called
42
42
  # without arguments:
43
- return self._impl.get_user().get_repos(affiliation='owner', **kwargs)
43
+ return self._impl.get_user().get_repos(affiliation="owner", **kwargs)
44
44
  else:
45
45
  return self._impl.get_user(user.name).get_repos(**kwargs)
46
46
  except GithubException:
@@ -13,7 +13,7 @@ from cgitize.repo import Repo, Visibility
13
13
 
14
14
  class GitLab:
15
15
  def __init__(self, token):
16
- self._impl = Gitlab('https://gitlab.com', private_token=token)
16
+ self._impl = Gitlab("https://gitlab.com", private_token=token)
17
17
 
18
18
  def get_repo(self, repo):
19
19
  try:
@@ -5,14 +5,14 @@
5
5
 
6
6
 
7
7
  def update(path, success, error=None):
8
- with open(path, 'w') as file:
9
- contents = ''
8
+ with open(path, "w") as file:
9
+ contents = ""
10
10
  if not success:
11
11
  contents = (
12
- '''<p style="text-align: center; color: red; font-weight: bold;">'''
12
+ """<p style="text-align: center; color: red; font-weight: bold;">"""
13
13
  )
14
- contents += '''Some repositories couldn't be updated, please check application logs for details.'''
14
+ contents += """Some repositories couldn't be updated, please check application logs for details."""
15
15
  if error is not None:
16
- contents += f'''<br>{type(error).__name__}: {error}'''
17
- contents += '''</p>\n'''
16
+ contents += f"""<br>{type(error).__name__}: {error}"""
17
+ contents += """</p>\n"""
18
18
  file.write(contents)
@@ -19,23 +19,23 @@ def parse_args(argv=None):
19
19
  argv = sys.argv[1:]
20
20
  parser = ArgumentParser()
21
21
  parser.add_argument(
22
- '--config',
23
- '-c',
24
- metavar='PATH',
22
+ "--config",
23
+ "-c",
24
+ metavar="PATH",
25
25
  default=Config.DEFAULT_PATH,
26
- help='config file path',
26
+ help="config file path",
27
27
  )
28
28
  parser.add_argument(
29
- '--repo', metavar='REPO_ID', nargs='*', dest='repos', help='repos to pull'
29
+ "--repo", metavar="REPO_ID", nargs="*", dest="repos", help="repos to pull"
30
30
  )
31
31
  parser.add_argument(
32
- '--force', '-f', action='store_true', help='overwrite existing repositories'
32
+ "--force", "-f", action="store_true", help="overwrite existing repositories"
33
33
  )
34
34
  parser.add_argument(
35
- '--verbose', '-v', action='store_true', help='verbose log output'
35
+ "--verbose", "-v", action="store_true", help="verbose log output"
36
36
  )
37
37
  parser.add_argument(
38
- '--version', '-V', action='version', version=f'%(prog)s {__version__}'
38
+ "--version", "-V", action="version", version=f"%(prog)s {__version__}"
39
39
  )
40
40
  return parser.parse_args(argv)
41
41
 
@@ -60,15 +60,15 @@ def main(argv=None):
60
60
  error = e
61
61
 
62
62
  if success:
63
- logging.info('All repositories were updated successfully')
63
+ logging.info("All repositories were updated successfully")
64
64
  else:
65
65
  logging.warning("Some repositories couldn't be updated!")
66
66
  if error is not None:
67
- logging.warning('Error: %s', error)
67
+ logging.warning("Error: %s", error)
68
68
 
69
69
  update_header(config.main.error_header_path, success, error)
70
70
  return int(not success)
71
71
 
72
72
 
73
- if __name__ == '__main__':
73
+ if __name__ == "__main__":
74
74
  sys.exit(main())