aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2021-03-30 01:25:35 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2021-03-30 01:25:35 +0300
commit25308812f0dab570fe05fea9d704673d562d53e2 (patch)
tree59989f83ff85e00e0f7f2bd1a26d63771b67eec6
parentcgitize.cgit: factor out setup_git_auth (diff)
downloadcgitize-25308812f0dab570fe05fea9d704673d562d53e2.tar.gz
cgitize-25308812f0dab570fe05fea9d704673d562d53e2.zip
cgitize.git: proper config writer classes
-rw-r--r--cgitize/git.py103
1 files changed, 99 insertions, 4 deletions
diff --git a/cgitize/git.py b/cgitize/git.py
index a2be8df..78679d7 100644
--- a/cgitize/git.py
+++ b/cgitize/git.py
@@ -39,6 +39,102 @@ class Config:
finally:
self.write(old_contents)
+ # What follows is an exteremely loose interpretation of what the .gitconfig
+ # syntax is. The source was git-config(1).
+
+ class Section:
+ def __init__(self, name, variables):
+ Config.Section.validate_name(name)
+ self.name = name
+ self.variables = variables
+
+ @staticmethod
+ def validate_name(name):
+ if not name:
+ raise RuntimeError('section names cannot be empty')
+ for c in name:
+ if c.isalnum() or c == '-' or c == '.':
+ continue
+ raise RuntimeError(f'section names must only contain alphanumeric characters, . or -: {name}')
+
+ @staticmethod
+ def format_name(name):
+ return name
+
+ def format(self):
+ result = '[self.format_name(self.name)]\n'
+ result += ''.join((var.format() for var in self.variables))
+ return result
+
+ class Subsection:
+ def __init__(self, section, name, variables):
+ Config.Section.validate_name(section)
+ Config.Subsection.validate_name(name)
+ self.section = section
+ self.name = name
+ self.variables = variables
+
+ @staticmethod
+ def validate_name(name):
+ if '\n' in name:
+ raise RuntimeError(f'subsection names cannot contain newlines: {name}')
+
+ def format_name(self):
+ name = self.name
+ # Escape the backslashes:
+ name = name.replace('\\', '\\\\')
+ # Escape the quotes:
+ name = name.replace('"', '\\"')
+ # Put in quotes:
+ return f'"{name}"'
+
+ def format(self):
+ result = f'[{Config.Section.format_name(self.section)} {self.format_name()}]\n'
+ result += ''.join((var.format() for var in self.variables))
+ return result
+
+ class Variable:
+ def __init__(self, name, value):
+ Config.Variable.validate_name(name)
+ Config.Variable.validate_value(value)
+ self.name = name
+ self.value = value
+
+ @staticmethod
+ def validate_name(name):
+ if not name:
+ raise RuntimeError('variable names cannot be empty')
+ for c in name:
+ if c.isalnum() or c == '-':
+ continue
+ raise RuntimeError(f'variable name can only contain alphanumeric characters or -: {name}')
+ if not name[0].isalnum():
+ raise RuntimeError(f'variable name must start with an alphanumeric character: {name}')
+
+ @staticmethod
+ def validate_value(value):
+ pass
+
+ def format_name(self):
+ return self.name
+
+ def format_value(self):
+ value = self.value
+ # Escape the backslashes:
+ value = value.replace('\\', '\\\\')
+ # Escape the supported escape sequences (\n, \t and \b):
+ value = value.replace('\n', '\\n')
+ value = value.replace('\t', '\\t')
+ value = value.replace('\b', '\\b')
+ # Escape the quotes:
+ value = value.replace('"', '\\"')
+ # Put in quotes:
+ value = f'"{value}"'
+ return value
+
+ def format(self):
+ return f' {self.format_name()} = {self.format_value()}\n'
+
class Git:
EXE = 'git'
@@ -64,9 +160,8 @@ class Git:
config = Git.get_global_config()
with utils.protected_file(config.path):
with config.backup() as old_contents:
- new_contents = f'''{old_contents}
-[url "{repo.clone_url_with_auth}"]
- insteadOf = {repo.clone_url}
-'''
+ variables = [Config.Variable('insteadOf', repo.clone_url)]
+ subsection = Config.Subsection('url', repo.clone_url_with_auth, variables)
+ new_contents = f'{old_contents}\n{subsection.format()}'
config.write(new_contents)
yield