- commit
- ca93ddb84b07a99c75efcf88cc3035544124d3b5
- parent
- b0b3e29be7cc75d64781d0797fdc5fee97a45eaa
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2024-09-05 09:52
python: lint
Diffstat
M | gitolite/shell.py | 64 | ++++++++++++++++++++++++++++++------------------------------ |
M | gitolite/stagit.py | 199 | ++++++++++++++++++++++++++++++------------------------------- |
M | src/ctpl.py | 98 | ++++++++++++++++++++++++++++++------------------------------ |
3 files changed, 180 insertions, 181 deletions
diff --git a/gitolite/shell.py b/gitolite/shell.py
@@ -2,48 +2,48 @@ 2 2 # see man git-shell 3 3 4 4 import os5 -1 import sys6 5 import re 7 6 import subprocess -1 7 import sys 8 8 9 9 import stagit 10 10 11 11 SOC_RE = (12 -1 r"^(git-receive-pack|git-upload-pack|git-upload-archive) "13 -1 r"'?/?([a-z0-9_:-]+)(\.git)?/?'?$"-1 12 r"^(git-receive-pack|git-upload-pack|git-upload-archive) " -1 13 r"'?/?([a-z0-9_:-]+)(\.git)?/?'?$" 14 14 ) 15 15 16 16 17 17 def parse_soc():18 -1 soc = re.match(SOC_RE, os.environ['SSH_ORIGINAL_COMMAND'])19 -1 if not soc:20 -1 sys.stderr.write('invalid command\n')21 -1 sys.exit(1)22 -1 cmd, repo, _ = soc.groups()23 -1 return cmd, repo-1 18 soc = re.match(SOC_RE, os.environ['SSH_ORIGINAL_COMMAND']) -1 19 if not soc: -1 20 sys.stderr.write('invalid command\n') -1 21 sys.exit(1) -1 22 cmd, repo, _ = soc.groups() -1 23 return cmd, repo 24 24 25 25 26 26 if __name__ == '__main__':27 -1 user = sys.argv[1]28 -129 -1 if 'SSH_ORIGINAL_COMMAND' not in os.environ:30 -1 for repo in stagit.config.iter_repos():31 -1 if stagit.config.can_ssh(repo, user):32 -1 print(repo)33 -1 sys.exit(0)34 -135 -1 cmd, repo = parse_soc()36 -137 -1 if not stagit.config.can_ssh(repo, user):38 -1 sys.stderr.write('access denied\n')39 -1 sys.exit(1)40 -141 -1 sys.exit(subprocess.call(42 -1 [*cmd.split('-', 1), repo],43 -1 cwd=stagit.REPO_DIR,44 -1 env={45 -1 **os.environ,46 -1 'STAGIT_USER': user,47 -1 'STAGIT_REPO': repo,48 -1 },49 -1 ))-1 27 user = sys.argv[1] -1 28 -1 29 if 'SSH_ORIGINAL_COMMAND' not in os.environ: -1 30 for repo in stagit.config.iter_repos(): -1 31 if stagit.config.can_ssh(repo, user): -1 32 print(repo) -1 33 sys.exit(0) -1 34 -1 35 cmd, repo = parse_soc() -1 36 -1 37 if not stagit.config.can_ssh(repo, user): -1 38 sys.stderr.write('access denied\n') -1 39 sys.exit(1) -1 40 -1 41 sys.exit(subprocess.call( -1 42 [*cmd.split('-', 1), repo], -1 43 cwd=stagit.REPO_DIR, -1 44 env={ -1 45 **os.environ, -1 46 'STAGIT_USER': user, -1 47 'STAGIT_REPO': repo, -1 48 }, -1 49 ))
diff --git a/gitolite/stagit.py b/gitolite/stagit.py
@@ -1,9 +1,8 @@ -1 1 import configparser 1 2 import os2 -1 import sys3 -1 import stat4 3 import shutil 5 4 import subprocess6 -1 import configparser-1 5 import sys 7 6 from xml.sax.saxutils import escape 8 7 9 8 USER = 'git' @@ -14,137 +13,137 @@ CONF_PATH = os.path.expanduser('~/stagit.conf') 14 13 15 14 16 15 if os.environ.get('USER') != USER:17 -1 sys.stderr.write('wrong user\n')18 -1 sys.exit(1)-1 16 sys.stderr.write('wrong user\n') -1 17 sys.exit(1) 19 18 20 19 21 20 def create_sh_script(path, lines):22 -1 if lines:23 -1 with open(path, 'w') as fh:24 -1 fh.write('#!/bin/sh\n')25 -1 for line in lines:26 -1 fh.write(line + '\n')27 -1 os.chmod(path, 0o775)28 -1 elif os.path.exists(path):29 -1 os.unlink(path)-1 21 if lines: -1 22 with open(path, 'w') as fh: -1 23 fh.write('#!/bin/sh\n') -1 24 for line in lines: -1 25 fh.write(line + '\n') -1 26 os.chmod(path, 0o775) -1 27 elif os.path.exists(path): -1 28 os.unlink(path) 30 29 31 30 32 31 def touch(path):33 -1 with open(path, 'a'):34 -1 os.utime(path, None)-1 32 with open(path, 'a'): -1 33 os.utime(path, None) 35 34 36 35 37 36 def get_repo_dir(repo):38 -1 return os.path.join(REPO_DIR, repo + '.git')-1 37 return os.path.join(REPO_DIR, repo + '.git') 39 38 40 39 41 40 class Config:42 -1 def __init__(self):43 -1 self.config = configparser.ConfigParser()44 -1 self.config.read(CONF_PATH)-1 41 def __init__(self): -1 42 self.config = configparser.ConfigParser() -1 43 self.config.read(CONF_PATH) 45 4446 -1 def get(self, section, key):47 -1 return self.config.get(section, key, fallback='')-1 45 def get(self, section, key): -1 46 return self.config.get(section, key, fallback='') 48 4749 -1 def getboolean(self, section, key):50 -1 return self.config.getboolean(section, key, fallback=False)-1 48 def getboolean(self, section, key): -1 49 return self.config.getboolean(section, key, fallback=False) 51 5052 -1 def can_ssh(self, repo, user):53 -1 allowed = self.get(repo, 'ssh').split()54 -1 return user in allowed or '@all' in allowed-1 51 def can_ssh(self, repo, user): -1 52 allowed = self.get(repo, 'ssh').split() -1 53 return user in allowed or '@all' in allowed 55 5456 -1 def iter_repos(self):57 -1 for key in self.config:58 -1 if key != 'DEFAULT':59 -1 yield key-1 55 def iter_repos(self): -1 56 for key in self.config: -1 57 if key != 'DEFAULT': -1 58 yield key 60 59 61 60 62 61 config = Config() 63 62 64 63 65 64 def update_repo(repo):66 -1 repodir = get_repo_dir(repo)67 -1 if not os.path.exists(repodir):68 -1 os.makedirs(repodir, exist_ok=True)69 -1 subprocess.check_call(['git', 'init', '--bare'], cwd=repodir)70 -171 -1 export_ok = os.path.join(repodir, 'git-daemon-export-ok')72 -1 post_update = []73 -1 if config.getboolean(repo, 'http'):74 -1 post_update.append(75 -1 'python3 -c \'import os, stagit; '76 -1 'stagit.render_repo(os.environ["STAGIT_REPO"])\''77 -1 )78 -1 touch(export_ok)79 -1 else:80 -1 if os.path.exists(export_ok):81 -1 os.unlink(export_ok)82 -183 -1 if config.get(repo, 'post-update'):84 -1 post_update.append(config.get(repo, 'post-update'))85 -1 create_sh_script(os.path.join(repodir, 'hooks', 'post-update'), post_update)86 -187 -1 with open(os.path.join(repodir, 'description'), 'w') as fh:88 -1 fh.write(config.get(repo, 'desc'))89 -1 with open(os.path.join(repodir, 'url'), 'w') as fh:90 -1 fh.write(config.get(repo, 'url'))-1 65 repodir = get_repo_dir(repo) -1 66 if not os.path.exists(repodir): -1 67 os.makedirs(repodir, exist_ok=True) -1 68 subprocess.check_call(['git', 'init', '--bare'], cwd=repodir) -1 69 -1 70 export_ok = os.path.join(repodir, 'git-daemon-export-ok') -1 71 post_update = [] -1 72 if config.getboolean(repo, 'http'): -1 73 post_update.append( -1 74 "python3 -c 'import os, stagit; " -1 75 'stagit.render_repo(os.environ["STAGIT_REPO"])\'' -1 76 ) -1 77 touch(export_ok) -1 78 else: -1 79 if os.path.exists(export_ok): -1 80 os.unlink(export_ok) -1 81 -1 82 if config.get(repo, 'post-update'): -1 83 post_update.append(config.get(repo, 'post-update')) -1 84 create_sh_script(os.path.join(repodir, 'hooks', 'post-update'), post_update) -1 85 -1 86 with open(os.path.join(repodir, 'description'), 'w') as fh: -1 87 fh.write(config.get(repo, 'desc')) -1 88 with open(os.path.join(repodir, 'url'), 'w') as fh: -1 89 fh.write(config.get(repo, 'url')) 91 90 92 91 93 92 def render_index():94 -1 fh = open(os.path.join(WWW_DIR, 'index.html'), 'w')95 -1 fh.write('<!DOCTYPE html>\n')96 -1 fh.write('<html>\n<head>\n')97 -1 fh.write('<meta charset="UTF-8">')98 -1 fh.write('<meta name="viewport" content="width=device-width">\n')99 -1 fh.write('<title>Repositories</title>\n')100 -1 fh.write('<link rel="stylesheet" type="text/css" href="style.css" />\n')101 -1 fh.write('</head>\n<body>\n')102 -1 fh.write('<h1>Repositories</h1>')103 -1 fh.write('<hr/>\n')104 -1 fh.write('<main id="content">\n')105 -1 fh.write('<table>\n<thead>\n')106 -1 fh.write('<tr><th>Name</th><th>Description</th></tr>\n')107 -1 fh.write('</thead>\n<tbody>\n')108 -1 for repo in config.iter_repos():109 -1 if config.getboolean(repo, 'http'):110 -1 fh.write('<tr><td><a href="%s/">%s</a></td><td>%s</td></tr>\n' % (111 -1 escape(repo), escape(repo), escape(config.get(repo, 'desc'))112 -1 ))113 -1 fh.write('</tbody>\n</table>\n')114 -1 fh.write('</main>\n</body>\n</html>\n')115 -1 fh.close()-1 93 fh = open(os.path.join(WWW_DIR, 'index.html'), 'w') -1 94 fh.write('<!DOCTYPE html>\n') -1 95 fh.write('<html>\n<head>\n') -1 96 fh.write('<meta charset="UTF-8">') -1 97 fh.write('<meta name="viewport" content="width=device-width">\n') -1 98 fh.write('<title>Repositories</title>\n') -1 99 fh.write('<link rel="stylesheet" type="text/css" href="style.css" />\n') -1 100 fh.write('</head>\n<body>\n') -1 101 fh.write('<h1>Repositories</h1>') -1 102 fh.write('<hr/>\n') -1 103 fh.write('<main id="content">\n') -1 104 fh.write('<table>\n<thead>\n') -1 105 fh.write('<tr><th>Name</th><th>Description</th></tr>\n') -1 106 fh.write('</thead>\n<tbody>\n') -1 107 for repo in config.iter_repos(): -1 108 if config.getboolean(repo, 'http'): -1 109 fh.write('<tr><td><a href="{}/">{}</a></td><td>{}</td></tr>\n'.format( -1 110 escape(repo), escape(repo), escape(config.get(repo, 'desc')) -1 111 )) -1 112 fh.write('</tbody>\n</table>\n') -1 113 fh.write('</main>\n</body>\n</html>\n') -1 114 fh.close() 116 115 117 116 118 117 def render_repo(repo):119 -1 print('Generating HTML for %s…' % repo)120 -1 target_dir = os.path.join(WWW_DIR, repo)121 -1 if os.path.isdir(target_dir):122 -1 shutil.rmtree(target_dir)123 -1 os.makedirs(target_dir)124 -1 subprocess.check_call(['stagit', get_repo_dir(repo)], cwd=target_dir)-1 118 print(f'Generating HTML for {repo}…') -1 119 target_dir = os.path.join(WWW_DIR, repo) -1 120 if os.path.isdir(target_dir): -1 121 shutil.rmtree(target_dir) -1 122 os.makedirs(target_dir) -1 123 subprocess.check_call(['stagit', get_repo_dir(repo)], cwd=target_dir) 125 124 126 125 127 126 def render_all():128 -1 for repo in os.listdir(WWW_DIR):129 -1 path = os.path.join(WWW_DIR, repo)130 -1 if os.path.isdir(path):131 -1 shutil.rmtree(path)132 -1 for repo in config.iter_repos():133 -1 if config.getboolean(repo, 'http'):134 -1 render_repo(repo)135 -1 render_index()-1 127 for repo in os.listdir(WWW_DIR): -1 128 path = os.path.join(WWW_DIR, repo) -1 129 if os.path.isdir(path): -1 130 shutil.rmtree(path) -1 131 for repo in config.iter_repos(): -1 132 if config.getboolean(repo, 'http'): -1 133 render_repo(repo) -1 134 render_index() 136 135 137 136 138 137 if __name__ == '__main__':139 -1 all_repos = set(config.iter_repos())140 -1 phy_repos = set(fn[:-4] for fn in os.listdir(REPO_DIR) if fn.endswith('.git'))141 -1 stale_repos = phy_repos - all_repos-1 138 all_repos = set(config.iter_repos()) -1 139 phy_repos = set(fn[:-4] for fn in os.listdir(REPO_DIR) if fn.endswith('.git')) -1 140 stale_repos = phy_repos - all_repos 142 141143 -1 print('Updating repos …')144 -1 for repo in all_repos:145 -1 update_repo(repo)-1 142 print('Updating repos …') -1 143 for repo in all_repos: -1 144 update_repo(repo) 146 145147 -1 if stale_repos:148 -1 print('Warning: stale files for deleted repos:', ', '.join(stale_repos))-1 146 if stale_repos: -1 147 print('Warning: stale files for deleted repos:', ', '.join(stale_repos)) 149 148150 -1 render_all()-1 149 render_all()
diff --git a/src/ctpl.py b/src/ctpl.py
@@ -1,66 +1,66 @@1 -1 import sys2 1 import re -1 2 import sys 3 3 4 4 5 5 def tokenize(s):6 -1 tokens = []7 -1 start = 08 -1 for i, c in enumerate(s):9 -1 if c == '{':10 -1 if i > start:11 -1 tokens.append((True, s[start:i]))12 -1 start = i + 113 -1 elif c == '}':14 -1 if i > start:15 -1 tokens.append((False, s[start:i]))16 -1 start = i + 117 -1 if i + 1 > start:18 -1 tokens.append((True, s[start:i+1]))19 -1 return tokens-1 6 tokens = [] -1 7 start = 0 -1 8 for i, c in enumerate(s): -1 9 if c == '{': -1 10 if i > start: -1 11 tokens.append((True, s[start:i])) -1 12 start = i + 1 -1 13 elif c == '}': -1 14 if i > start: -1 15 tokens.append((False, s[start:i])) -1 16 start = i + 1 -1 17 if i + 1 > start: -1 18 tokens.append((True, s[start:i+1])) -1 19 return tokens 20 20 21 21 22 22 def print_safe(s, args):23 -1 if args:24 -1 return ['fprintf(fp, "%s", %s);' % (s, ', '.join(args))]25 -1 elif s:26 -1 return ['fputs("%s", fp);' % s]27 -1 return []-1 23 if args: -1 24 return [f'fprintf(fp, "{s}", {", ".join(args)});'] -1 25 elif s: -1 26 return [f'fputs("{s}", fp);'] -1 27 return [] 28 28 29 29 30 30 def parse_line(indent, tpl):31 -1 lines = []32 -1 s = ''33 -1 args = []34 -1 for is_text, token in tokenize(tpl):35 -1 if is_text:36 -1 s += token37 -1 elif ':%' in token:38 -1 arg, placeholder = token.split(':', 1)39 -1 s += placeholder40 -1 args.append(arg)41 -1 else:42 -1 lines += print_safe(s, args)43 -1 s = ''44 -1 args = []-1 31 lines = [] -1 32 s = '' -1 33 args = [] -1 34 for is_text, token in tokenize(tpl): -1 35 if is_text: -1 36 s += token -1 37 elif ':%' in token: -1 38 arg, placeholder = token.split(':', 1) -1 39 s += placeholder -1 40 args.append(arg) -1 41 else: -1 42 lines += print_safe(s, args) -1 43 s = '' -1 44 args = [] 45 4546 -1 if ':' in token:47 -1 arg, l = token.split(':', 1)48 -1 else:49 -1 arg = token50 -1 l = 'strlen(%s)' % token-1 46 if ':' in token: -1 47 arg, length = token.split(':', 1) -1 48 else: -1 49 arg = token -1 50 length = f'strlen({token})' 51 5152 -1 lines.append('xmlencode(fp, %s, %s);' % (arg, l))53 -1 lines += print_safe(s, args)-1 52 lines.append(f'xmlencode(fp, {arg}, {length});') -1 53 lines += print_safe(s, args) 54 5455 -1 print(indent + ' '.join(lines))-1 55 print(indent + ' '.join(lines)) 56 56 57 57 58 58 if __name__ == '__main__':59 -1 fh = open(sys.argv[1])-1 59 fh = open(sys.argv[1]) 60 6061 -1 for line in fh:62 -1 match = re.match(r'(\s*)T\("(.*)"\);\n$', line)63 -1 if match:64 -1 parse_line(*match.groups())65 -1 else:66 -1 print(line.rstrip())-1 61 for line in fh: -1 62 match = re.match(r'(\s*)T\("(.*)"\);\n$', line) -1 63 if match: -1 64 parse_line(*match.groups()) -1 65 else: -1 66 print(line.rstrip())