[aur-dev] [PATCH 00/17] Add tests for Python scripts
Various changes in the way Python scripts and tests are organized. Shared Python modules are now placed in a site-packages directory. Tests for mkpkglists, tuvotereminder, pkgmaint and aurblup are added. Lukas Fleischer (17): Add a main() method to all Python scripts git-auth: Move entry point to a main() method git-serve: Pass user and privileges as parameters git-serve: Move entry point to a main() method git-update: Move entry point to a main() method Use setuptools to install Python modules Use config and db in scripts Make test suite paths top-level directory relative Reorganize tests Update README mkpkglists: Make output files configurable Add tests for mkpkglists Add tests for tuvotereminder scripts: Do not use UNIX_TIMESTAMP Add tests for pkgmaint aurblup: Drop support for multiple servers Add tests for aurblup README | 6 + aurweb/__init__.py | 0 {git-interface => aurweb}/config.py | 0 {git-interface => aurweb}/db.py | 16 +- conf/config.proto | 6 +- git-interface/__init__.py | 0 git-interface/git-auth.py | 58 ++-- git-interface/git-serve.py | 270 ++++++++++--------- git-interface/git-update.py | 300 +++++++++++---------- scripts/__init__.py | 0 scripts/aurblup.py | 105 ++++---- scripts/mkpkglists.py | 71 +++-- scripts/notify.py | 278 ++++++++++--------- scripts/pkgmaint.py | 31 +-- scripts/popupdate.py | 52 ++-- scripts/tuvotereminder.py | 40 ++- setup.py | 20 ++ {git-interface/test => test}/Makefile | 0 {git-interface/test => test}/setup.sh | 29 +- {git-interface/test => test}/sharness.sh | 0 .../test/t0001-auth.sh => test/t1100-git-auth.sh | 0 .../test/t0002-serve.sh => test/t1200-git-serve.sh | 0 .../t0003-update.sh => test/t1300-git-update.sh | 0 test/t2100-mkpkglists.sh | 47 ++++ test/t2200-tuvotereminder.sh | 26 ++ test/t2300-pkgmaint.sh | 26 ++ test/t2400-aurblup.sh | 53 ++++ 27 files changed, 818 insertions(+), 616 deletions(-) create mode 100644 aurweb/__init__.py rename {git-interface => aurweb}/config.py (100%) rename {git-interface => aurweb}/db.py (73%) create mode 100644 git-interface/__init__.py create mode 100644 scripts/__init__.py create mode 100644 setup.py rename {git-interface/test => test}/Makefile (100%) rename {git-interface/test => test}/setup.sh (89%) rename {git-interface/test => test}/sharness.sh (100%) rename git-interface/test/t0001-auth.sh => test/t1100-git-auth.sh (100%) rename git-interface/test/t0002-serve.sh => test/t1200-git-serve.sh (100%) rename git-interface/test/t0003-update.sh => test/t1300-git-update.sh (100%) create mode 100755 test/t2100-mkpkglists.sh create mode 100755 test/t2200-tuvotereminder.sh create mode 100755 test/t2300-pkgmaint.sh create mode 100755 test/t2400-aurblup.sh -- 2.10.0
Move the main program logic of all scripts to main() methods such that they can be used as modules and easily be invoked by setuptools wrapper scripts. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- scripts/aurblup.py | 86 +++++++++++++++++++++++++---------------------- scripts/mkpkglists.py | 52 ++++++++++++++++------------ scripts/notify.py | 6 +++- scripts/pkgmaint.py | 23 ++++++++----- scripts/popupdate.py | 31 ++++++++++------- scripts/tuvotereminder.py | 28 +++++++++------ 6 files changed, 132 insertions(+), 94 deletions(-) diff --git a/scripts/aurblup.py b/scripts/aurblup.py index 6733b45..07119b5 100755 --- a/scripts/aurblup.py +++ b/scripts/aurblup.py @@ -18,43 +18,49 @@ db_path = config.get('aurblup', 'db-path') sync_dbs = config.get('aurblup', 'sync-dbs').split(' ') servers = config.get('aurblup', 'servers').split(' ') -blacklist = set() -providers = set() -repomap = dict() - -h = pyalpm.Handle("/", db_path) -for sync_db in sync_dbs: - repo = h.register_syncdb(sync_db, pyalpm.SIG_DATABASE_OPTIONAL) - repo.servers = [server.replace("%s", sync_db) for server in servers] - t = h.init_transaction() - repo.update(False) - t.release() - - for pkg in repo.pkgcache: - blacklist.add(pkg.name) - [blacklist.add(x) for x in pkg.replaces] - providers.add((pkg.name, pkg.name)) - repomap[(pkg.name, pkg.name)] = repo.name - for provision in pkg.provides: - provisionname = re.sub(r'(<|=|>).*', '', provision) - providers.add((pkg.name, provisionname)) - repomap[(pkg.name, provisionname)] = repo.name - -db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) -cur = db.cursor() - -cur.execute("SELECT Name, Provides FROM OfficialProviders") -oldproviders = set(cur.fetchall()) - -for pkg, provides in providers.difference(oldproviders): - repo = repomap[(pkg, provides)] - cur.execute("INSERT INTO OfficialProviders (Name, Repo, Provides) " - "VALUES (%s, %s, %s)", [pkg, repo, provides]) -for pkg, provides in oldproviders.difference(providers): - cur.execute("DELETE FROM OfficialProviders " - "WHERE Name = %s AND Provides = %s", [pkg, provides]) - -db.commit() -db.close() + +def main(): + blacklist = set() + providers = set() + repomap = dict() + + h = pyalpm.Handle("/", db_path) + for sync_db in sync_dbs: + repo = h.register_syncdb(sync_db, pyalpm.SIG_DATABASE_OPTIONAL) + repo.servers = [server.replace("%s", sync_db) for server in servers] + t = h.init_transaction() + repo.update(False) + t.release() + + for pkg in repo.pkgcache: + blacklist.add(pkg.name) + [blacklist.add(x) for x in pkg.replaces] + providers.add((pkg.name, pkg.name)) + repomap[(pkg.name, pkg.name)] = repo.name + for provision in pkg.provides: + provisionname = re.sub(r'(<|=|>).*', '', provision) + providers.add((pkg.name, provisionname)) + repomap[(pkg.name, provisionname)] = repo.name + + db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, + passwd=aur_db_pass, db=aur_db_name, + unix_socket=aur_db_socket, buffered=True) + cur = db.cursor() + + cur.execute("SELECT Name, Provides FROM OfficialProviders") + oldproviders = set(cur.fetchall()) + + for pkg, provides in providers.difference(oldproviders): + repo = repomap[(pkg, provides)] + cur.execute("INSERT INTO OfficialProviders (Name, Repo, Provides) " + "VALUES (%s, %s, %s)", [pkg, repo, provides]) + for pkg, provides in oldproviders.difference(providers): + cur.execute("DELETE FROM OfficialProviders " + "WHERE Name = %s AND Provides = %s", [pkg, provides]) + + db.commit() + db.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/mkpkglists.py b/scripts/mkpkglists.py index a6f8a19..8cab0a9 100755 --- a/scripts/mkpkglists.py +++ b/scripts/mkpkglists.py @@ -17,25 +17,33 @@ aur_db_user = config.get('database', 'user') aur_db_pass = config.get('database', 'password') aur_db_socket = config.get('database', 'socket') -db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) -cur = db.cursor() - -datestr = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") -pkglist_header = "# AUR package list, generated on " + datestr -pkgbaselist_header = "# AUR package base list, generated on " + datestr - -with gzip.open(docroot + "packages.gz", "w") as f: - f.write(bytes(pkglist_header + "\n", "UTF-8")) - cur.execute("SELECT Packages.Name FROM Packages INNER JOIN PackageBases " + - "ON PackageBases.ID = Packages.PackageBaseID " + - "WHERE PackageBases.PackagerUID IS NOT NULL") - f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) - -with gzip.open(docroot + "pkgbase.gz", "w") as f: - f.write(bytes(pkgbaselist_header + "\n", "UTF-8")) - cur.execute("SELECT Name FROM PackageBases WHERE PackagerUID IS NOT NULL") - f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) - -db.close() + +def main(): + db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, + passwd=aur_db_pass, db=aur_db_name, + unix_socket=aur_db_socket, buffered=True) + cur = db.cursor() + + datestr = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") + pkglist_header = "# AUR package list, generated on " + datestr + pkgbaselist_header = "# AUR package base list, generated on " + datestr + + with gzip.open(docroot + "packages.gz", "w") as f: + f.write(bytes(pkglist_header + "\n", "UTF-8")) + cur.execute("SELECT Packages.Name FROM Packages " + + "INNER JOIN PackageBases " + + "ON PackageBases.ID = Packages.PackageBaseID " + + "WHERE PackageBases.PackagerUID IS NOT NULL") + f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) + + with gzip.open(docroot + "pkgbase.gz", "w") as f: + f.write(bytes(pkgbaselist_header + "\n", "UTF-8")) + cur.execute("SELECT Name FROM PackageBases " + + "WHERE PackagerUID IS NOT NULL") + f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) + + db.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/notify.py b/scripts/notify.py index aeb59c3..cc99747 100755 --- a/scripts/notify.py +++ b/scripts/notify.py @@ -427,7 +427,7 @@ def tu_vote_reminder(cur, vote_id): send_notification(to, subject, body, refs) -if __name__ == '__main__': +def main(): action = sys.argv[1] action_map = { 'send-resetkey': send_resetkey, @@ -454,3 +454,7 @@ if __name__ == '__main__': db.commit() db.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/pkgmaint.py b/scripts/pkgmaint.py index 0eb9422..346b046 100755 --- a/scripts/pkgmaint.py +++ b/scripts/pkgmaint.py @@ -13,13 +13,20 @@ aur_db_user = config.get('database', 'user') aur_db_pass = config.get('database', 'password') aur_db_socket = config.get('database', 'socket') -db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) -cur = db.cursor() -cur.execute("DELETE FROM PackageBases WHERE " + - "UNIX_TIMESTAMP() - SubmittedTS > 86400 AND PackagerUID IS NULL") +def main(): + db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, + passwd=aur_db_pass, db=aur_db_name, + unix_socket=aur_db_socket, buffered=True) + cur = db.cursor() -db.commit() -db.close() + cur.execute("DELETE FROM PackageBases WHERE " + + "UNIX_TIMESTAMP() - SubmittedTS > 86400 " + + "AND PackagerUID IS NULL") + + db.commit() + db.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/popupdate.py b/scripts/popupdate.py index f3ba513..26d8379 100755 --- a/scripts/popupdate.py +++ b/scripts/popupdate.py @@ -13,18 +13,25 @@ aur_db_user = config.get('database', 'user') aur_db_pass = config.get('database', 'password') aur_db_socket = config.get('database', 'socket') -db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) -cur = db.cursor() -cur.execute("UPDATE PackageBases SET NumVotes = (SELECT COUNT(*) FROM " + - "PackageVotes WHERE PackageVotes.PackageBaseID = PackageBases.ID)") +def main(): + db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, + passwd=aur_db_pass, db=aur_db_name, + unix_socket=aur_db_socket, buffered=True) + cur = db.cursor() -cur.execute("UPDATE PackageBases SET Popularity = (" + - "SELECT COALESCE(SUM(POWER(0.98, (UNIX_TIMESTAMP() - VoteTS) / 86400)), 0.0) " + - "FROM PackageVotes WHERE PackageVotes.PackageBaseID = " + - "PackageBases.ID AND NOT VoteTS IS NULL)") + cur.execute("UPDATE PackageBases SET NumVotes = (" + + "SELECT COUNT(*) FROM PackageVotes " + + "WHERE PackageVotes.PackageBaseID = PackageBases.ID)") -db.commit() -db.close() + cur.execute("UPDATE PackageBases SET Popularity = (" + + "SELECT COALESCE(SUM(POWER(0.98, (UNIX_TIMESTAMP() - VoteTS) / 86400)), 0.0) " + + "FROM PackageVotes WHERE PackageVotes.PackageBaseID = " + + "PackageBases.ID AND NOT VoteTS IS NULL)") + + db.commit() + db.close() + + +if __name__ == '__main__': + main() diff --git a/scripts/tuvotereminder.py b/scripts/tuvotereminder.py index 0992623..dc16397 100755 --- a/scripts/tuvotereminder.py +++ b/scripts/tuvotereminder.py @@ -16,17 +16,23 @@ aur_db_pass = config.get('database', 'password') aur_db_socket = config.get('database', 'socket') notify_cmd = config.get('notifications', 'notify-cmd') -db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) -cur = db.cursor() -now = int(time.time()) -filter_from = now + 500 -filter_to = now + 172800 +def main(): + db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, + passwd=aur_db_pass, db=aur_db_name, + unix_socket=aur_db_socket, buffered=True) + cur = db.cursor() -cur.execute("SELECT ID FROM TU_VoteInfo WHERE End >= %s AND End <= %s", - [filter_from, filter_to]) + now = int(time.time()) + filter_from = now + 500 + filter_to = now + 172800 -for vote_id in [row[0] for row in cur.fetchall()]: - subprocess.Popen((notify_cmd, 'tu-vote-reminder', str(vote_id))) + cur.execute("SELECT ID FROM TU_VoteInfo WHERE End >= %s AND End <= %s", + [filter_from, filter_to]) + + for vote_id in [row[0] for row in cur.fetchall()]: + subprocess.Popen((notify_cmd, 'tu-vote-reminder', str(vote_id))) + + +if __name__ == '__main__': + main() -- 2.10.0
Move the main program logic of git-auth to a main() method such that it can be used as a module and easily be invoked by setuptools wrapper scripts. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- git-interface/git-auth.py | 54 +++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/git-interface/git-auth.py b/git-interface/git-auth.py index 45fd577..d3b0188 100755 --- a/git-interface/git-auth.py +++ b/git-interface/git-auth.py @@ -23,36 +23,40 @@ def format_command(env_vars, command, ssh_opts, ssh_key): return msg -valid_keytypes = config.get('auth', 'valid-keytypes').split() -username_regex = config.get('auth', 'username-regex') -git_serve_cmd = config.get('auth', 'git-serve-cmd') -ssh_opts = config.get('auth', 'ssh-options') +def main(): + valid_keytypes = config.get('auth', 'valid-keytypes').split() + username_regex = config.get('auth', 'username-regex') + git_serve_cmd = config.get('auth', 'git-serve-cmd') + ssh_opts = config.get('auth', 'ssh-options') -keytype = sys.argv[1] -keytext = sys.argv[2] -if keytype not in valid_keytypes: - exit(1) + keytype = sys.argv[1] + keytext = sys.argv[2] + if keytype not in valid_keytypes: + exit(1) -conn = db.Connection() + conn = db.Connection() -cur = conn.execute("SELECT Users.Username, Users.AccountTypeID FROM Users " + - "INNER JOIN SSHPubKeys ON SSHPubKeys.UserID = Users.ID " - "WHERE SSHPubKeys.PubKey = ? AND Users.Suspended = 0", - (keytype + " " + keytext,)) + cur = conn.execute("SELECT Users.Username, Users.AccountTypeID FROM Users " + "INNER JOIN SSHPubKeys ON SSHPubKeys.UserID = Users.ID " + "WHERE SSHPubKeys.PubKey = ? AND Users.Suspended = 0", + (keytype + " " + keytext,)) -row = cur.fetchone() -if not row or cur.fetchone(): - exit(1) + row = cur.fetchone() + if not row or cur.fetchone(): + exit(1) -user, account_type = row -if not re.match(username_regex, user): - exit(1) + user, account_type = row + if not re.match(username_regex, user): + exit(1) + env_vars = { + 'AUR_USER': user, + 'AUR_PRIVILEGED': '1' if account_type > 1 else '0', + } + key = keytype + ' ' + keytext -env_vars = { - 'AUR_USER': user, - 'AUR_PRIVILEGED': '1' if account_type > 1 else '0', -} -key = keytype + ' ' + keytext + print(format_command(env_vars, git_serve_cmd, ssh_opts, key)) -print(format_command(env_vars, git_serve_cmd, ssh_opts, key)) + +if __name__ == '__main__': + main() -- 2.10.0
Move the main program logic of git-server to a main() method such that it can be used as a module and easily be invoked by setuptools wrapper scripts. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- git-interface/git-serve.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/git-interface/git-serve.py b/git-interface/git-serve.py index 47e7df9..ddec144 100755 --- a/git-interface/git-serve.py +++ b/git-interface/git-serve.py @@ -76,7 +76,7 @@ def create_pkgbase(pkgbase, user): conn.close() -def pkgbase_adopt(pkgbase): +def pkgbase_adopt(pkgbase, user, privileged): pkgbase_id = pkgbase_from_name(pkgbase) if not pkgbase_id: die('{:s}: package base not found: {:s}'.format(action, pkgbase)) @@ -124,7 +124,7 @@ def pkgbase_get_comaintainers(pkgbase): return [row[0] for row in cur.fetchall()] -def pkgbase_set_comaintainers(pkgbase, userlist): +def pkgbase_set_comaintainers(pkgbase, userlist, user, privileged): pkgbase_id = pkgbase_from_name(pkgbase) if not pkgbase_id: die('{:s}: package base not found: {:s}'.format(action, pkgbase)) @@ -183,7 +183,7 @@ def pkgbase_set_comaintainers(pkgbase, userlist): conn.close() -def pkgbase_disown(pkgbase): +def pkgbase_disown(pkgbase, user, privileged): pkgbase_id = pkgbase_from_name(pkgbase) if not pkgbase_id: die('{:s}: package base not found: {:s}'.format(action, pkgbase)) @@ -211,7 +211,7 @@ def pkgbase_disown(pkgbase): new_maintainer_userid = cur.fetchone()[0] comaintainers.remove(new_maintainer) - pkgbase_set_comaintainers(pkgbase, comaintainers) + pkgbase_set_comaintainers(pkgbase, comaintainers, user, privileged) cur = conn.execute("UPDATE PackageBases SET MaintainerUID = ? " + "WHERE ID = ?", [new_maintainer_userid, pkgbase_id]) @@ -365,7 +365,7 @@ elif action == 'adopt': die_with_help("{:s}: too many arguments".format(action)) pkgbase = cmdargv[1] - pkgbase_adopt(pkgbase) + pkgbase_adopt(pkgbase, user, privileged) elif action == 'disown': if len(cmdargv) < 2: die_with_help("{:s}: missing repository name".format(action)) @@ -373,14 +373,14 @@ elif action == 'disown': die_with_help("{:s}: too many arguments".format(action)) pkgbase = cmdargv[1] - pkgbase_disown(pkgbase) + pkgbase_disown(pkgbase, user, privileged) elif action == 'set-comaintainers': if len(cmdargv) < 2: die_with_help("{:s}: missing repository name".format(action)) pkgbase = cmdargv[1] userlist = cmdargv[2:] - pkgbase_set_comaintainers(pkgbase, userlist) + pkgbase_set_comaintainers(pkgbase, userlist, user, privileged) elif action == 'help': cmds = { "adopt <name>": "Adopt a package base.", -- 2.10.0
Move the main program logic of git-serve to a main() method such that it can be used as a module and easily be invoked by setuptools wrapper scripts. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- git-interface/git-serve.py | 222 +++++++++++++++++++++++---------------------- 1 file changed, 114 insertions(+), 108 deletions(-) diff --git a/git-interface/git-serve.py b/git-interface/git-serve.py index ddec144..8bcecd2 100755 --- a/git-interface/git-serve.py +++ b/git-interface/git-serve.py @@ -289,111 +289,117 @@ def usage(cmds): exit(0) -user = os.environ.get('AUR_USER') -privileged = (os.environ.get('AUR_PRIVILEGED', '0') == '1') -ssh_cmd = os.environ.get('SSH_ORIGINAL_COMMAND') -ssh_client = os.environ.get('SSH_CLIENT') - -if not ssh_cmd: - die_with_help("Interactive shell is disabled.") -cmdargv = shlex.split(ssh_cmd) -action = cmdargv[0] -remote_addr = ssh_client.split(' ')[0] if ssh_client else None - -if enable_maintenance: - if remote_addr not in maintenance_exc: - die("The AUR is down due to maintenance. We will be back soon.") - -if action == 'git-upload-pack' or action == 'git-receive-pack': - if len(cmdargv) < 2: - die_with_help("{:s}: missing path".format(action)) - - path = cmdargv[1].rstrip('/') - if not path.startswith('/'): - path = '/' + path - if not path.endswith('.git'): - path = path + '.git' - pkgbase = path[1:-4] - if not re.match(repo_regex, pkgbase): - die('{:s}: invalid repository name: {:s}'.format(action, pkgbase)) - - if action == 'git-receive-pack' and pkgbase_exists(pkgbase): - if not privileged and not pkgbase_has_write_access(pkgbase, user): - die('{:s}: permission denied: {:s}'.format(action, user)) - - os.environ["AUR_USER"] = user - os.environ["AUR_PKGBASE"] = pkgbase - os.environ["GIT_NAMESPACE"] = pkgbase - cmd = action + " '" + repo_path + "'" - os.execl(git_shell_cmd, git_shell_cmd, '-c', cmd) -elif action == 'set-keywords': - if len(cmdargv) < 2: - die_with_help("{:s}: missing repository name".format(action)) - pkgbase_set_keywords(cmdargv[1], cmdargv[2:]) -elif action == 'list-repos': - if len(cmdargv) > 1: - die_with_help("{:s}: too many arguments".format(action)) - list_repos(user) -elif action == 'setup-repo': - if len(cmdargv) < 2: - die_with_help("{:s}: missing repository name".format(action)) - if len(cmdargv) > 2: - die_with_help("{:s}: too many arguments".format(action)) - warn('{:s} is deprecated. Use `git push` to create new repositories.'.format(action)) - create_pkgbase(cmdargv[1], user) -elif action == 'restore': - if len(cmdargv) < 2: - die_with_help("{:s}: missing repository name".format(action)) - if len(cmdargv) > 2: - die_with_help("{:s}: too many arguments".format(action)) - - pkgbase = cmdargv[1] - if not re.match(repo_regex, pkgbase): - die('{:s}: invalid repository name: {:s}'.format(action, pkgbase)) - - if pkgbase_exists(pkgbase): - die('{:s}: package base exists: {:s}'.format(action, pkgbase)) - create_pkgbase(pkgbase, user) - - os.environ["AUR_USER"] = user - os.environ["AUR_PKGBASE"] = pkgbase - os.execl(git_update_cmd, git_update_cmd, 'restore') -elif action == 'adopt': - if len(cmdargv) < 2: - die_with_help("{:s}: missing repository name".format(action)) - if len(cmdargv) > 2: - die_with_help("{:s}: too many arguments".format(action)) - - pkgbase = cmdargv[1] - pkgbase_adopt(pkgbase, user, privileged) -elif action == 'disown': - if len(cmdargv) < 2: - die_with_help("{:s}: missing repository name".format(action)) - if len(cmdargv) > 2: - die_with_help("{:s}: too many arguments".format(action)) - - pkgbase = cmdargv[1] - pkgbase_disown(pkgbase, user, privileged) -elif action == 'set-comaintainers': - if len(cmdargv) < 2: - die_with_help("{:s}: missing repository name".format(action)) - - pkgbase = cmdargv[1] - userlist = cmdargv[2:] - pkgbase_set_comaintainers(pkgbase, userlist, user, privileged) -elif action == 'help': - cmds = { - "adopt <name>": "Adopt a package base.", - "disown <name>": "Disown a package base.", - "help": "Show this help message and exit.", - "list-repos": "List all your repositories.", - "restore <name>": "Restore a deleted package base.", - "set-comaintainers <name> [...]": "Set package base co-maintainers.", - "set-keywords <name> [...]": "Change package base keywords.", - "setup-repo <name>": "Create a repository (deprecated).", - "git-receive-pack": "Internal command used with Git.", - "git-upload-pack": "Internal command used with Git.", - } - usage(cmds) -else: - die_with_help("invalid command: {:s}".format(action)) +def main(): + user = os.environ.get('AUR_USER') + privileged = (os.environ.get('AUR_PRIVILEGED', '0') == '1') + ssh_cmd = os.environ.get('SSH_ORIGINAL_COMMAND') + ssh_client = os.environ.get('SSH_CLIENT') + + if not ssh_cmd: + die_with_help("Interactive shell is disabled.") + cmdargv = shlex.split(ssh_cmd) + action = cmdargv[0] + remote_addr = ssh_client.split(' ')[0] if ssh_client else None + + if enable_maintenance: + if remote_addr not in maintenance_exc: + die("The AUR is down due to maintenance. We will be back soon.") + + if action == 'git-upload-pack' or action == 'git-receive-pack': + if len(cmdargv) < 2: + die_with_help("{:s}: missing path".format(action)) + + path = cmdargv[1].rstrip('/') + if not path.startswith('/'): + path = '/' + path + if not path.endswith('.git'): + path = path + '.git' + pkgbase = path[1:-4] + if not re.match(repo_regex, pkgbase): + die('{:s}: invalid repository name: {:s}'.format(action, pkgbase)) + + if action == 'git-receive-pack' and pkgbase_exists(pkgbase): + if not privileged and not pkgbase_has_write_access(pkgbase, user): + die('{:s}: permission denied: {:s}'.format(action, user)) + + os.environ["AUR_USER"] = user + os.environ["AUR_PKGBASE"] = pkgbase + os.environ["GIT_NAMESPACE"] = pkgbase + cmd = action + " '" + repo_path + "'" + os.execl(git_shell_cmd, git_shell_cmd, '-c', cmd) + elif action == 'set-keywords': + if len(cmdargv) < 2: + die_with_help("{:s}: missing repository name".format(action)) + pkgbase_set_keywords(cmdargv[1], cmdargv[2:]) + elif action == 'list-repos': + if len(cmdargv) > 1: + die_with_help("{:s}: too many arguments".format(action)) + list_repos(user) + elif action == 'setup-repo': + if len(cmdargv) < 2: + die_with_help("{:s}: missing repository name".format(action)) + if len(cmdargv) > 2: + die_with_help("{:s}: too many arguments".format(action)) + warn('{:s} is deprecated. ' + 'Use `git push` to create new repositories.'.format(action)) + create_pkgbase(cmdargv[1], user) + elif action == 'restore': + if len(cmdargv) < 2: + die_with_help("{:s}: missing repository name".format(action)) + if len(cmdargv) > 2: + die_with_help("{:s}: too many arguments".format(action)) + + pkgbase = cmdargv[1] + if not re.match(repo_regex, pkgbase): + die('{:s}: invalid repository name: {:s}'.format(action, pkgbase)) + + if pkgbase_exists(pkgbase): + die('{:s}: package base exists: {:s}'.format(action, pkgbase)) + create_pkgbase(pkgbase, user) + + os.environ["AUR_USER"] = user + os.environ["AUR_PKGBASE"] = pkgbase + os.execl(git_update_cmd, git_update_cmd, 'restore') + elif action == 'adopt': + if len(cmdargv) < 2: + die_with_help("{:s}: missing repository name".format(action)) + if len(cmdargv) > 2: + die_with_help("{:s}: too many arguments".format(action)) + + pkgbase = cmdargv[1] + pkgbase_adopt(pkgbase, user, privileged) + elif action == 'disown': + if len(cmdargv) < 2: + die_with_help("{:s}: missing repository name".format(action)) + if len(cmdargv) > 2: + die_with_help("{:s}: too many arguments".format(action)) + + pkgbase = cmdargv[1] + pkgbase_disown(pkgbase, user, privileged) + elif action == 'set-comaintainers': + if len(cmdargv) < 2: + die_with_help("{:s}: missing repository name".format(action)) + + pkgbase = cmdargv[1] + userlist = cmdargv[2:] + pkgbase_set_comaintainers(pkgbase, userlist, user, privileged) + elif action == 'help': + cmds = { + "adopt <name>": "Adopt a package base.", + "disown <name>": "Disown a package base.", + "help": "Show this help message and exit.", + "list-repos": "List all your repositories.", + "restore <name>": "Restore a deleted package base.", + "set-comaintainers <name> [...]": "Set package base co-maintainers.", + "set-keywords <name> [...]": "Change package base keywords.", + "setup-repo <name>": "Create a repository (deprecated).", + "git-receive-pack": "Internal command used with Git.", + "git-upload-pack": "Internal command used with Git.", + } + usage(cmds) + else: + die_with_help("invalid command: {:s}".format(action)) + + +if __name__ == '__main__': + main() -- 2.10.0
Move the main program logic of git-update to a main() method such that it can be used as a module and easily be invoked by setuptools wrapper scripts. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- git-interface/git-update.py | 294 +++++++++++++++++++++++--------------------- 1 file changed, 154 insertions(+), 140 deletions(-) diff --git a/git-interface/git-update.py b/git-interface/git-update.py index be4c9be..36c38ae 100755 --- a/git-interface/git-update.py +++ b/git-interface/git-update.py @@ -233,173 +233,187 @@ def die_commit(msg, commit): exit(1) -repo = pygit2.Repository(repo_path) - -user = os.environ.get("AUR_USER") -pkgbase = os.environ.get("AUR_PKGBASE") -privileged = (os.environ.get("AUR_PRIVILEGED", '0') == '1') -warn_or_die = warn if privileged else die - -if len(sys.argv) == 2 and sys.argv[1] == "restore": - if 'refs/heads/' + pkgbase not in repo.listall_references(): - die('{:s}: repository not found: {:s}'.format(sys.argv[1], pkgbase)) - refname = "refs/heads/master" - sha1_old = sha1_new = repo.lookup_reference('refs/heads/' + pkgbase).target -elif len(sys.argv) == 4: - refname, sha1_old, sha1_new = sys.argv[1:4] -else: - die("invalid arguments") - -if refname != "refs/heads/master": - die("pushing to a branch other than master is restricted") - -conn = db.Connection() - -# Detect and deny non-fast-forwards. -if sha1_old != "0000000000000000000000000000000000000000" and not privileged: - walker = repo.walk(sha1_old, pygit2.GIT_SORT_TOPOLOGICAL) - walker.hide(sha1_new) - if next(walker, None) is not None: - die("denying non-fast-forward (you should pull first)") - -# Prepare the walker that validates new commits. -walker = repo.walk(sha1_new, pygit2.GIT_SORT_TOPOLOGICAL) -if sha1_old != "0000000000000000000000000000000000000000": - walker.hide(sha1_old) - -# Validate all new commits. -for commit in walker: - for fname in ('.SRCINFO', 'PKGBUILD'): - if fname not in commit.tree: - die_commit("missing {:s}".format(fname), str(commit.id)) - - for treeobj in commit.tree: - blob = repo[treeobj.id] - - if isinstance(blob, pygit2.Tree): - die_commit("the repository must not contain subdirectories", - str(commit.id)) +def main(): + repo = pygit2.Repository(repo_path) + + user = os.environ.get("AUR_USER") + pkgbase = os.environ.get("AUR_PKGBASE") + privileged = (os.environ.get("AUR_PRIVILEGED", '0') == '1') + warn_or_die = warn if privileged else die + + if len(sys.argv) == 2 and sys.argv[1] == "restore": + if 'refs/heads/' + pkgbase not in repo.listall_references(): + die('{:s}: repository not found: {:s}'.format(sys.argv[1], + pkgbase)) + refname = "refs/heads/master" + branchref = 'refs/heads/' + pkgbase + sha1_old = sha1_new = repo.lookup_reference(branchref).target + elif len(sys.argv) == 4: + refname, sha1_old, sha1_new = sys.argv[1:4] + else: + die("invalid arguments") - if not isinstance(blob, pygit2.Blob): - die_commit("not a blob object: {:s}".format(treeobj), - str(commit.id)) + if refname != "refs/heads/master": + die("pushing to a branch other than master is restricted") - if blob.size > max_blob_size: - die_commit("maximum blob size ({:s}) exceeded".format(size_humanize(max_blob_size)), str(commit.id)) + conn = db.Connection() - metadata_raw = repo[commit.tree['.SRCINFO'].id].data.decode() - (metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) - if errors: - sys.stderr.write("error: The following errors occurred " - "when parsing .SRCINFO in commit\n") - sys.stderr.write("error: {:s}:\n".format(str(commit.id))) - for error in errors: - for err in error['error']: - sys.stderr.write("error: line {:d}: {:s}\n".format(error['line'], err)) - exit(1) + # Detect and deny non-fast-forwards. + if sha1_old != "0" * 40 and not privileged: + walker = repo.walk(sha1_old, pygit2.GIT_SORT_TOPOLOGICAL) + walker.hide(sha1_new) + if next(walker, None) is not None: + die("denying non-fast-forward (you should pull first)") - metadata_pkgbase = metadata['pkgbase'] - if not re.match(repo_regex, metadata_pkgbase): - die_commit('invalid pkgbase: {:s}'.format(metadata_pkgbase), - str(commit.id)) + # Prepare the walker that validates new commits. + walker = repo.walk(sha1_new, pygit2.GIT_SORT_TOPOLOGICAL) + if sha1_old != "0" * 40: + walker.hide(sha1_old) - for pkgname in set(metadata['packages'].keys()): - pkginfo = srcinfo.utils.get_merged_package(pkgname, metadata) + # Validate all new commits. + for commit in walker: + for fname in ('.SRCINFO', 'PKGBUILD'): + if fname not in commit.tree: + die_commit("missing {:s}".format(fname), str(commit.id)) - for field in ('pkgver', 'pkgrel', 'pkgname'): - if field not in pkginfo: - die_commit('missing mandatory field: {:s}'.format(field), + for treeobj in commit.tree: + blob = repo[treeobj.id] + + if isinstance(blob, pygit2.Tree): + die_commit("the repository must not contain subdirectories", str(commit.id)) - if 'epoch' in pkginfo and not pkginfo['epoch'].isdigit(): - die_commit('invalid epoch: {:s}'.format(pkginfo['epoch']), - str(commit.id)) + if not isinstance(blob, pygit2.Blob): + die_commit("not a blob object: {:s}".format(treeobj), + str(commit.id)) - if not re.match(r'[a-z0-9][a-z0-9\.+_-]*$', pkginfo['pkgname']): - die_commit('invalid package name: {:s}'.format(pkginfo['pkgname']), + if blob.size > max_blob_size: + die_commit("maximum blob size ({:s}) exceeded".format( + size_humanize(max_blob_size)), str(commit.id)) + + metadata_raw = repo[commit.tree['.SRCINFO'].id].data.decode() + (metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) + if errors: + sys.stderr.write("error: The following errors occurred " + "when parsing .SRCINFO in commit\n") + sys.stderr.write("error: {:s}:\n".format(str(commit.id))) + for error in errors: + for err in error['error']: + sys.stderr.write("error: line {:d}: {:s}\n".format( + error['line'], err)) + exit(1) + + metadata_pkgbase = metadata['pkgbase'] + if not re.match(repo_regex, metadata_pkgbase): + die_commit('invalid pkgbase: {:s}'.format(metadata_pkgbase), str(commit.id)) - for field in ('pkgname', 'pkgdesc', 'url'): - if field in pkginfo and len(pkginfo[field]) > 255: - die_commit('{:s} field too long: {:s}'.format(field, pkginfo[field]), - str(commit.id)) + for pkgname in set(metadata['packages'].keys()): + pkginfo = srcinfo.utils.get_merged_package(pkgname, metadata) - for field in ('install', 'changelog'): - if field in pkginfo and not pkginfo[field] in commit.tree: - die_commit('missing {:s} file: {:s}'.format(field, pkginfo[field]), - str(commit.id)) + for field in ('pkgver', 'pkgrel', 'pkgname'): + if field not in pkginfo: + die_commit('missing mandatory field: {:s}'.format(field), + str(commit.id)) - for field in extract_arch_fields(pkginfo, 'source'): - fname = field['value'] - if "://" in fname or "lp:" in fname: - continue - if fname not in commit.tree: - die_commit('missing source file: {:s}'.format(fname), + if 'epoch' in pkginfo and not pkginfo['epoch'].isdigit(): + die_commit('invalid epoch: {:s}'.format(pkginfo['epoch']), str(commit.id)) + if not re.match(r'[a-z0-9][a-z0-9\.+_-]*$', pkginfo['pkgname']): + die_commit('invalid package name: {:s}'.format( + pkginfo['pkgname']), str(commit.id)) + + for field in ('pkgname', 'pkgdesc', 'url'): + if field in pkginfo and len(pkginfo[field]) > 255: + die_commit('{:s} field too long: {:s}'.format(field, + pkginfo[field]), str(commit.id)) + + for field in ('install', 'changelog'): + if field in pkginfo and not pkginfo[field] in commit.tree: + die_commit('missing {:s} file: {:s}'.format(field, + pkginfo[field]), str(commit.id)) + + for field in extract_arch_fields(pkginfo, 'source'): + fname = field['value'] + if "://" in fname or "lp:" in fname: + continue + if fname not in commit.tree: + die_commit('missing source file: {:s}'.format(fname), + str(commit.id)) + + # Display a warning if .SRCINFO is unchanged. + if sha1_old not in ("0000000000000000000000000000000000000000", sha1_new): + srcinfo_id_old = repo[sha1_old].tree['.SRCINFO'].id + srcinfo_id_new = repo[sha1_new].tree['.SRCINFO'].id + if srcinfo_id_old == srcinfo_id_new: + warn(".SRCINFO unchanged. " + "The package database will not be updated!") + + # Read .SRCINFO from the HEAD commit. + metadata_raw = repo[repo[sha1_new].tree['.SRCINFO'].id].data.decode() + (metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) -# Display a warning if .SRCINFO is unchanged. -if sha1_old not in ("0000000000000000000000000000000000000000", sha1_new): - srcinfo_id_old = repo[sha1_old].tree['.SRCINFO'].id - srcinfo_id_new = repo[sha1_new].tree['.SRCINFO'].id - if srcinfo_id_old == srcinfo_id_new: - warn(".SRCINFO unchanged. The package database will not be updated!") + # Ensure that the package base name matches the repository name. + metadata_pkgbase = metadata['pkgbase'] + if metadata_pkgbase != pkgbase: + die('invalid pkgbase: {:s}, expected {:s}'.format(metadata_pkgbase, + pkgbase)) -# Read .SRCINFO from the HEAD commit. -metadata_raw = repo[repo[sha1_new].tree['.SRCINFO'].id].data.decode() -(metadata, errors) = srcinfo.parse.parse_srcinfo(metadata_raw) + # Ensure that packages are neither blacklisted nor overwritten. + pkgbase = metadata['pkgbase'] + cur = conn.execute("SELECT ID FROM PackageBases WHERE Name = ?", [pkgbase]) + row = cur.fetchone() + pkgbase_id = row[0] if row else 0 -# Ensure that the package base name matches the repository name. -metadata_pkgbase = metadata['pkgbase'] -if metadata_pkgbase != pkgbase: - die('invalid pkgbase: {:s}, expected {:s}'.format(metadata_pkgbase, pkgbase)) + cur = conn.execute("SELECT Name FROM PackageBlacklist") + blacklist = [row[0] for row in cur.fetchall()] -# Ensure that packages are neither blacklisted nor overwritten. -pkgbase = metadata['pkgbase'] -cur = conn.execute("SELECT ID FROM PackageBases WHERE Name = ?", [pkgbase]) -row = cur.fetchone() -pkgbase_id = row[0] if row else 0 + cur = conn.execute("SELECT Name, Repo FROM OfficialProviders") + providers = dict(cur.fetchall()) -cur = conn.execute("SELECT Name FROM PackageBlacklist") -blacklist = [row[0] for row in cur.fetchall()] + for pkgname in srcinfo.utils.get_package_names(metadata): + pkginfo = srcinfo.utils.get_merged_package(pkgname, metadata) + pkgname = pkginfo['pkgname'] -cur = conn.execute("SELECT Name, Repo FROM OfficialProviders") -providers = dict(cur.fetchall()) + if pkgname in blacklist: + warn_or_die('package is blacklisted: {:s}'.format(pkgname)) + if pkgname in providers: + warn_or_die('package already provided by [{:s}]: {:s}'.format( + providers[pkgname], pkgname)) -for pkgname in srcinfo.utils.get_package_names(metadata): - pkginfo = srcinfo.utils.get_merged_package(pkgname, metadata) - pkgname = pkginfo['pkgname'] + cur = conn.execute("SELECT COUNT(*) FROM Packages WHERE Name = ? " + + "AND PackageBaseID <> ?", [pkgname, pkgbase_id]) + if cur.fetchone()[0] > 0: + die('cannot overwrite package: {:s}'.format(pkgname)) - if pkgname in blacklist: - warn_or_die('package is blacklisted: {:s}'.format(pkgname)) - if pkgname in providers: - warn_or_die('package already provided by [{:s}]: {:s}'.format(providers[pkgname], pkgname)) + # Create a new package base if it does not exist yet. + if pkgbase_id == 0: + pkgbase_id = create_pkgbase(conn, pkgbase, user) - cur = conn.execute("SELECT COUNT(*) FROM Packages WHERE Name = ? AND " + - "PackageBaseID <> ?", [pkgname, pkgbase_id]) - if cur.fetchone()[0] > 0: - die('cannot overwrite package: {:s}'.format(pkgname)) + # Store package base details in the database. + save_metadata(metadata, conn, user) -# Create a new package base if it does not exist yet. -if pkgbase_id == 0: - pkgbase_id = create_pkgbase(conn, pkgbase, user) + # Create (or update) a branch with the name of the package base for better + # accessibility. + branchref = 'refs/heads/' + pkgbase + repo.create_reference(branchref, sha1_new, True) -# Store package base details in the database. -save_metadata(metadata, conn, user) + # Work around a Git bug: The HEAD ref is not updated when using + # gitnamespaces. This can be removed once the bug fix is included in Git + # mainline. See + # http://git.661346.n2.nabble.com/PATCH-receive-pack-Create-a-HEAD-ref-for-ref... + # for details. + headref = 'refs/namespaces/' + pkgbase + '/HEAD' + repo.create_reference(headref, sha1_new, True) -# Create (or update) a branch with the name of the package base for better -# accessibility. -repo.create_reference('refs/heads/' + pkgbase, sha1_new, True) + # Send package update notifications. + update_notify(conn, user, pkgbase_id) -# Work around a Git bug: The HEAD ref is not updated when using gitnamespaces. -# This can be removed once the bug fix is included in Git mainline. See -# http://git.661346.n2.nabble.com/PATCH-receive-pack-Create-a-HEAD-ref-for-ref... -# for details. -repo.create_reference('refs/namespaces/' + pkgbase + '/HEAD', sha1_new, True) + # Close the database. + cur.close() + conn.close() -# Send package update notifications. -update_notify(conn, user, pkgbase_id) -# Close the database. -cur.close() -conn.close() +if __name__ == '__main__': + main() -- 2.10.0
Instead of using relative imports, add support for installing the config and db Python modules to a proper location using setuptools. Change all git-interface scripts to access those modules from the search path. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- aurweb/__init__.py | 0 {git-interface => aurweb}/config.py | 0 {git-interface => aurweb}/db.py | 16 +++++++-------- git-interface/__init__.py | 0 git-interface/git-auth.py | 14 ++++++------- git-interface/git-serve.py | 40 ++++++++++++++++++------------------- git-interface/git-update.py | 14 ++++++------- git-interface/test/setup.sh | 4 ++++ scripts/__init__.py | 0 setup.py | 20 +++++++++++++++++++ 10 files changed, 66 insertions(+), 42 deletions(-) create mode 100644 aurweb/__init__.py rename {git-interface => aurweb}/config.py (100%) rename {git-interface => aurweb}/db.py (73%) create mode 100644 git-interface/__init__.py create mode 100644 scripts/__init__.py create mode 100644 setup.py diff --git a/aurweb/__init__.py b/aurweb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/git-interface/config.py b/aurweb/config.py similarity index 100% rename from git-interface/config.py rename to aurweb/config.py diff --git a/git-interface/db.py b/aurweb/db.py similarity index 73% rename from git-interface/db.py rename to aurweb/db.py index 75d2283..0b58197 100644 --- a/git-interface/db.py +++ b/aurweb/db.py @@ -1,7 +1,7 @@ import mysql.connector import sqlite3 -import config +import aurweb.config class Connection: @@ -9,14 +9,14 @@ class Connection: _paramstyle = None def __init__(self): - aur_db_backend = config.get('database', 'backend') + aur_db_backend = aurweb.config.get('database', 'backend') if aur_db_backend == 'mysql': - aur_db_host = config.get('database', 'host') - aur_db_name = config.get('database', 'name') - aur_db_user = config.get('database', 'user') - aur_db_pass = config.get('database', 'password') - aur_db_socket = config.get('database', 'socket') + aur_db_host = aurweb.config.get('database', 'host') + aur_db_name = aurweb.config.get('database', 'name') + aur_db_user = aurweb.config.get('database', 'user') + aur_db_pass = aurweb.config.get('database', 'password') + aur_db_socket = aurweb.config.get('database', 'socket') self._conn = mysql.connector.connect(host=aur_db_host, user=aur_db_user, passwd=aur_db_pass, @@ -25,7 +25,7 @@ class Connection: buffered=True) self._paramstyle = mysql.connector.paramstyle elif aur_db_backend == 'sqlite': - aur_db_name = config.get('database', 'name') + aur_db_name = aurweb.config.get('database', 'name') self._conn = sqlite3.connect(aur_db_name) self._paramstyle = sqlite3.paramstyle else: diff --git a/git-interface/__init__.py b/git-interface/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/git-interface/git-auth.py b/git-interface/git-auth.py index d3b0188..022b0ff 100755 --- a/git-interface/git-auth.py +++ b/git-interface/git-auth.py @@ -4,8 +4,8 @@ import shlex import re import sys -import config -import db +import aurweb.config +import aurweb.db def format_command(env_vars, command, ssh_opts, ssh_key): @@ -24,17 +24,17 @@ def format_command(env_vars, command, ssh_opts, ssh_key): def main(): - valid_keytypes = config.get('auth', 'valid-keytypes').split() - username_regex = config.get('auth', 'username-regex') - git_serve_cmd = config.get('auth', 'git-serve-cmd') - ssh_opts = config.get('auth', 'ssh-options') + valid_keytypes = aurweb.config.get('auth', 'valid-keytypes').split() + username_regex = aurweb.config.get('auth', 'username-regex') + git_serve_cmd = aurweb.config.get('auth', 'git-serve-cmd') + ssh_opts = aurweb.config.get('auth', 'ssh-options') keytype = sys.argv[1] keytext = sys.argv[2] if keytype not in valid_keytypes: exit(1) - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT Users.Username, Users.AccountTypeID FROM Users " "INNER JOIN SSHPubKeys ON SSHPubKeys.UserID = Users.ID " diff --git a/git-interface/git-serve.py b/git-interface/git-serve.py index 8bcecd2..5f3b26d 100755 --- a/git-interface/git-serve.py +++ b/git-interface/git-serve.py @@ -7,23 +7,23 @@ import subprocess import sys import time -import config -import db +import aurweb.config +import aurweb.db -notify_cmd = config.get('notifications', 'notify-cmd') +notify_cmd = aurweb.config.get('notifications', 'notify-cmd') -repo_path = config.get('serve', 'repo-path') -repo_regex = config.get('serve', 'repo-regex') -git_shell_cmd = config.get('serve', 'git-shell-cmd') -git_update_cmd = config.get('serve', 'git-update-cmd') -ssh_cmdline = config.get('serve', 'ssh-cmdline') +repo_path = aurweb.config.get('serve', 'repo-path') +repo_regex = aurweb.config.get('serve', 'repo-regex') +git_shell_cmd = aurweb.config.get('serve', 'git-shell-cmd') +git_update_cmd = aurweb.config.get('serve', 'git-update-cmd') +ssh_cmdline = aurweb.config.get('serve', 'ssh-cmdline') -enable_maintenance = config.getboolean('options', 'enable-maintenance') -maintenance_exc = config.get('options', 'maintenance-exceptions').split() +enable_maintenance = aurweb.config.getboolean('options', 'enable-maintenance') +maintenance_exc = aurweb.config.get('options', 'maintenance-exceptions').split() def pkgbase_from_name(pkgbase): - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT ID FROM PackageBases WHERE Name = ?", [pkgbase]) row = cur.fetchone() @@ -35,7 +35,7 @@ def pkgbase_exists(pkgbase): def list_repos(user): - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT ID FROM Users WHERE Username = ?", [user]) userid = cur.fetchone()[0] @@ -55,7 +55,7 @@ def create_pkgbase(pkgbase, user): if pkgbase_exists(pkgbase): die('{:s}: package base already exists: {:s}'.format(action, pkgbase)) - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT ID FROM Users WHERE Username = ?", [user]) userid = cur.fetchone()[0] @@ -81,7 +81,7 @@ def pkgbase_adopt(pkgbase, user, privileged): if not pkgbase_id: die('{:s}: package base not found: {:s}'.format(action, pkgbase)) - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT ID FROM PackageBases WHERE ID = ? AND " + "MaintainerUID IS NULL", [pkgbase_id]) @@ -111,7 +111,7 @@ def pkgbase_adopt(pkgbase, user, privileged): def pkgbase_get_comaintainers(pkgbase): - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT UserName FROM PackageComaintainers " + "INNER JOIN Users " + @@ -132,7 +132,7 @@ def pkgbase_set_comaintainers(pkgbase, userlist, user, privileged): if not privileged and not pkgbase_has_full_access(pkgbase, user): die('{:s}: permission denied: {:s}'.format(action, user)) - conn = db.Connection() + conn = aurweb.db.Connection() userlist_old = set(pkgbase_get_comaintainers(pkgbase)) @@ -198,7 +198,7 @@ def pkgbase_disown(pkgbase, user, privileged): comaintainers = [] new_maintainer_userid = None - conn = db.Connection() + conn = aurweb.db.Connection() # Make the first co-maintainer the new maintainer, unless the action was # enforced by a Trusted User. @@ -232,7 +232,7 @@ def pkgbase_set_keywords(pkgbase, keywords): if not pkgbase_id: die('{:s}: package base not found: {:s}'.format(action, pkgbase)) - conn = db.Connection() + conn = aurweb.db.Connection() conn.execute("DELETE FROM PackageKeywords WHERE PackageBaseID = ?", [pkgbase_id]) @@ -245,7 +245,7 @@ def pkgbase_set_keywords(pkgbase, keywords): def pkgbase_has_write_access(pkgbase, user): - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT COUNT(*) FROM PackageBases " + "LEFT JOIN PackageComaintainers " + @@ -259,7 +259,7 @@ def pkgbase_has_write_access(pkgbase, user): def pkgbase_has_full_access(pkgbase, user): - conn = db.Connection() + conn = aurweb.db.Connection() cur = conn.execute("SELECT COUNT(*) FROM PackageBases " + "INNER JOIN Users " + diff --git a/git-interface/git-update.py b/git-interface/git-update.py index 36c38ae..7337341 100755 --- a/git-interface/git-update.py +++ b/git-interface/git-update.py @@ -10,15 +10,15 @@ import time import srcinfo.parse import srcinfo.utils -import config -import db +import aurweb.config +import aurweb.db -notify_cmd = config.get('notifications', 'notify-cmd') +notify_cmd = aurweb.config.get('notifications', 'notify-cmd') -repo_path = config.get('serve', 'repo-path') -repo_regex = config.get('serve', 'repo-regex') +repo_path = aurweb.config.get('serve', 'repo-path') +repo_regex = aurweb.config.get('serve', 'repo-regex') -max_blob_size = config.getint('update', 'max-blob-size') +max_blob_size = aurweb.config.getint('update', 'max-blob-size') def size_humanize(num): @@ -256,7 +256,7 @@ def main(): if refname != "refs/heads/master": die("pushing to a branch other than master is restricted") - conn = db.Connection() + conn = aurweb.db.Connection() # Detect and deny non-fast-forwards. if sha1_old != "0" * 40 and not privileged: diff --git a/git-interface/test/setup.sh b/git-interface/test/setup.sh index f9c1616..d269af6 100644 --- a/git-interface/test/setup.sh +++ b/git-interface/test/setup.sh @@ -2,6 +2,10 @@ TEST_DIRECTORY="$(pwd)" . ./sharness.sh +# Configure python search path. +PYTHONPATH="$TEST_DIRECTORY/../../" +export PYTHONPATH + # Configure paths to the Git interface scripts. GIT_AUTH="$TEST_DIRECTORY/../git-auth.py" GIT_SERVE="$TEST_DIRECTORY/../git-serve.py" diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..48eb176 --- /dev/null +++ b/setup.py @@ -0,0 +1,20 @@ +import re +from setuptools import setup, find_packages +import sys + +version = None +with open('web/lib/version.inc.php', 'r') as f: + for line in f.readlines(): + match = re.match(r'^define\("AURWEB_VERSION", "v([0-9.]+)"\);$', line) + if match: + version = match.group(1) + +if not version: + sys.stderr.write('error: Failed to parse version file!') + sys.exit(1) + +setup( + name="aurweb", + version=version, + packages=find_packages(), +) -- 2.10.0
Instead of using configparser and mysql.connector directly, change all Python scripts to use the config and db Python modules which are now accessible from a common location. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- scripts/aurblup.py | 37 +++---- scripts/mkpkglists.py | 32 ++---- scripts/notify.py | 272 +++++++++++++++++++++++----------------------- scripts/pkgmaint.py | 28 ++--- scripts/popupdate.py | 40 +++---- scripts/tuvotereminder.py | 24 ++-- 6 files changed, 183 insertions(+), 250 deletions(-) diff --git a/scripts/aurblup.py b/scripts/aurblup.py index 07119b5..0009715 100755 --- a/scripts/aurblup.py +++ b/scripts/aurblup.py @@ -1,22 +1,14 @@ #!/usr/bin/python3 -import configparser -import mysql.connector -import os import pyalpm import re -config = configparser.RawConfigParser() -config.read(os.path.dirname(os.path.realpath(__file__)) + "/../conf/config") +import aurweb.config +import aurweb.db -aur_db_host = config.get('database', 'host') -aur_db_name = config.get('database', 'name') -aur_db_user = config.get('database', 'user') -aur_db_pass = config.get('database', 'password') -aur_db_socket = config.get('database', 'socket') -db_path = config.get('aurblup', 'db-path') -sync_dbs = config.get('aurblup', 'sync-dbs').split(' ') -servers = config.get('aurblup', 'servers').split(' ') +db_path = aurweb.config.get('aurblup', 'db-path') +sync_dbs = aurweb.config.get('aurblup', 'sync-dbs').split(' ') +servers = aurweb.config.get('aurblup', 'servers').split(' ') def main(): @@ -42,24 +34,21 @@ def main(): providers.add((pkg.name, provisionname)) repomap[(pkg.name, provisionname)] = repo.name - db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) - cur = db.cursor() + conn = aurweb.db.Connection() - cur.execute("SELECT Name, Provides FROM OfficialProviders") + cur = conn.execute("SELECT Name, Provides FROM OfficialProviders") oldproviders = set(cur.fetchall()) for pkg, provides in providers.difference(oldproviders): repo = repomap[(pkg, provides)] - cur.execute("INSERT INTO OfficialProviders (Name, Repo, Provides) " - "VALUES (%s, %s, %s)", [pkg, repo, provides]) + conn.execute("INSERT INTO OfficialProviders (Name, Repo, Provides) " + "VALUES (?, ?, ?)", [pkg, repo, provides]) for pkg, provides in oldproviders.difference(providers): - cur.execute("DELETE FROM OfficialProviders " - "WHERE Name = %s AND Provides = %s", [pkg, provides]) + conn.execute("DELETE FROM OfficialProviders " + "WHERE Name = ? AND Provides = ?", [pkg, provides]) - db.commit() - db.close() + conn.commit() + conn.close() if __name__ == '__main__': diff --git a/scripts/mkpkglists.py b/scripts/mkpkglists.py index 8cab0a9..70cbd13 100755 --- a/scripts/mkpkglists.py +++ b/scripts/mkpkglists.py @@ -1,28 +1,16 @@ #!/usr/bin/python3 -import configparser import datetime import gzip -import mysql.connector import os -docroot = os.path.dirname(os.path.realpath(__file__)) + "/../web/html/" - -config = configparser.RawConfigParser() -config.read(os.path.dirname(os.path.realpath(__file__)) + "/../conf/config") +import aurweb.db -aur_db_host = config.get('database', 'host') -aur_db_name = config.get('database', 'name') -aur_db_user = config.get('database', 'user') -aur_db_pass = config.get('database', 'password') -aur_db_socket = config.get('database', 'socket') +docroot = os.path.dirname(os.path.realpath(__file__)) + "/../web/html/" def main(): - db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) - cur = db.cursor() + conn = aurweb.db.Connection() datestr = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") pkglist_header = "# AUR package list, generated on " + datestr @@ -30,19 +18,19 @@ def main(): with gzip.open(docroot + "packages.gz", "w") as f: f.write(bytes(pkglist_header + "\n", "UTF-8")) - cur.execute("SELECT Packages.Name FROM Packages " + - "INNER JOIN PackageBases " + - "ON PackageBases.ID = Packages.PackageBaseID " + - "WHERE PackageBases.PackagerUID IS NOT NULL") + cur = conn.execute("SELECT Packages.Name FROM Packages " + + "INNER JOIN PackageBases " + + "ON PackageBases.ID = Packages.PackageBaseID " + + "WHERE PackageBases.PackagerUID IS NOT NULL") f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) with gzip.open(docroot + "pkgbase.gz", "w") as f: f.write(bytes(pkgbaselist_header + "\n", "UTF-8")) - cur.execute("SELECT Name FROM PackageBases " + - "WHERE PackagerUID IS NOT NULL") + cur = conn.execute("SELECT Name FROM PackageBases " + + "WHERE PackagerUID IS NOT NULL") f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) - db.close() + conn.close() if __name__ == '__main__': diff --git a/scripts/notify.py b/scripts/notify.py index cc99747..0f1a073 100755 --- a/scripts/notify.py +++ b/scripts/notify.py @@ -1,28 +1,19 @@ #!/usr/bin/python3 -import configparser import email.mime.text -import mysql.connector -import os import subprocess import sys import textwrap -config = configparser.RawConfigParser() -config.read(os.path.dirname(os.path.realpath(__file__)) + '/../conf/config') +import aurweb.config +import aurweb.db -aur_db_host = config.get('database', 'host') -aur_db_name = config.get('database', 'name') -aur_db_user = config.get('database', 'user') -aur_db_pass = config.get('database', 'password') -aur_db_socket = config.get('database', 'socket') +aur_location = aurweb.config.get('options', 'aur_location') +aur_request_ml = aurweb.config.get('options', 'aur_request_ml') -aur_location = config.get('options', 'aur_location') -aur_request_ml = config.get('options', 'aur_request_ml') - -sendmail = config.get('notifications', 'sendmail') -sender = config.get('notifications', 'sender') -reply_to = config.get('notifications', 'reply-to') +sendmail = aurweb.config.get('notifications', 'sendmail') +sender = aurweb.config.get('notifications', 'sender') +reply_to = aurweb.config.get('notifications', 'reply-to') def headers_cc(cclist): @@ -60,120 +51,126 @@ def send_notification(to, subject, body, refs, headers={}): p.communicate(msg.as_bytes()) -def username_from_id(cur, uid): - cur.execute('SELECT UserName FROM Users WHERE ID = %s', [uid]) +def username_from_id(conn, uid): + cur = conn.execute('SELECT UserName FROM Users WHERE ID = ?', [uid]) return cur.fetchone()[0] -def pkgbase_from_id(cur, pkgbase_id): - cur.execute('SELECT Name FROM PackageBases WHERE ID = %s', [pkgbase_id]) +def pkgbase_from_id(conn, pkgbase_id): + cur = conn.execute('SELECT Name FROM PackageBases WHERE ID = ?', + [pkgbase_id]) return cur.fetchone()[0] -def pkgbase_from_pkgreq(cur, reqid): - cur.execute('SELECT PackageBaseID FROM PackageRequests WHERE ID = %s', - [reqid]) +def pkgbase_from_pkgreq(conn, reqid): + cur = conn.execute('SELECT PackageBaseID FROM PackageRequests ' + + 'WHERE ID = ?', [reqid]) return cur.fetchone()[0] -def get_user_email(cur, uid): - cur.execute('SELECT Email FROM Users WHERE ID = %s', [uid]) +def get_user_email(conn, uid): + cur = conn.execute('SELECT Email FROM Users WHERE ID = ?', [uid]) return cur.fetchone()[0] -def get_maintainer_email(cur, pkgbase_id): - cur.execute('SELECT Users.Email FROM Users ' + - 'INNER JOIN PackageBases ' + - 'ON PackageBases.MaintainerUID = Users.ID WHERE ' + - 'PackageBases.ID = %s', [pkgbase_id]) +def get_maintainer_email(conn, pkgbase_id): + cur = conn.execute('SELECT Users.Email FROM Users ' + + 'INNER JOIN PackageBases ' + + 'ON PackageBases.MaintainerUID = Users.ID WHERE ' + + 'PackageBases.ID = ?', [pkgbase_id]) return cur.fetchone()[0] -def get_recipients(cur, pkgbase_id, uid): - cur.execute('SELECT DISTINCT Users.Email FROM Users ' + - 'INNER JOIN PackageNotifications ' + - 'ON PackageNotifications.UserID = Users.ID WHERE ' + - 'PackageNotifications.UserID != %s AND ' + - 'PackageNotifications.PackageBaseID = %s', [uid, pkgbase_id]) +def get_recipients(conn, pkgbase_id, uid): + cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' + + 'INNER JOIN PackageNotifications ' + + 'ON PackageNotifications.UserID = Users.ID WHERE ' + + 'PackageNotifications.UserID != ? AND ' + + 'PackageNotifications.PackageBaseID = ?', + [uid, pkgbase_id]) return [row[0] for row in cur.fetchall()] -def get_comment_recipients(cur, pkgbase_id, uid): - cur.execute('SELECT DISTINCT Users.Email FROM Users ' + - 'INNER JOIN PackageNotifications ' + - 'ON PackageNotifications.UserID = Users.ID WHERE ' + - 'Users.CommentNotify = 1 AND ' + - 'PackageNotifications.UserID != %s AND ' + - 'PackageNotifications.PackageBaseID = %s', [uid, pkgbase_id]) +def get_comment_recipients(conn, pkgbase_id, uid): + cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' + + 'INNER JOIN PackageNotifications ' + + 'ON PackageNotifications.UserID = Users.ID WHERE ' + + 'Users.CommentNotify = 1 AND ' + + 'PackageNotifications.UserID != ? AND ' + + 'PackageNotifications.PackageBaseID = ?', + [uid, pkgbase_id]) return [row[0] for row in cur.fetchall()] -def get_update_recipients(cur, pkgbase_id, uid): - cur.execute('SELECT DISTINCT Users.Email FROM Users ' + - 'INNER JOIN PackageNotifications ' + - 'ON PackageNotifications.UserID = Users.ID WHERE ' + - 'Users.UpdateNotify = 1 AND ' + - 'PackageNotifications.UserID != %s AND ' + - 'PackageNotifications.PackageBaseID = %s', [uid, pkgbase_id]) +def get_update_recipients(conn, pkgbase_id, uid): + cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' + + 'INNER JOIN PackageNotifications ' + + 'ON PackageNotifications.UserID = Users.ID WHERE ' + + 'Users.UpdateNotify = 1 AND ' + + 'PackageNotifications.UserID != ? AND ' + + 'PackageNotifications.PackageBaseID = ?', + [uid, pkgbase_id]) return [row[0] for row in cur.fetchall()] -def get_ownership_recipients(cur, pkgbase_id, uid): - cur.execute('SELECT DISTINCT Users.Email FROM Users ' + - 'INNER JOIN PackageNotifications ' + - 'ON PackageNotifications.UserID = Users.ID WHERE ' + - 'Users.OwnershipNotify = 1 AND ' + - 'PackageNotifications.UserID != %s AND ' + - 'PackageNotifications.PackageBaseID = %s', [uid, pkgbase_id]) +def get_ownership_recipients(conn, pkgbase_id, uid): + cur = conn.execute('SELECT DISTINCT Users.Email FROM Users ' + + 'INNER JOIN PackageNotifications ' + + 'ON PackageNotifications.UserID = Users.ID WHERE ' + + 'Users.OwnershipNotify = 1 AND ' + + 'PackageNotifications.UserID != ? AND ' + + 'PackageNotifications.PackageBaseID = ?', + [uid, pkgbase_id]) return [row[0] for row in cur.fetchall()] -def get_request_recipients(cur, reqid): - cur.execute('SELECT DISTINCT Users.Email FROM PackageRequests ' + - 'INNER JOIN PackageBases ' + - 'ON PackageBases.ID = PackageRequests.PackageBaseID ' + - 'INNER JOIN Users ' + - 'ON Users.ID = PackageRequests.UsersID ' + - 'OR Users.ID = PackageBases.MaintainerUID ' + - 'WHERE PackageRequests.ID = %s', [reqid]) +def get_request_recipients(conn, reqid): + cur = conn.execute('SELECT DISTINCT Users.Email FROM PackageRequests ' + + 'INNER JOIN PackageBases ' + + 'ON PackageBases.ID = PackageRequests.PackageBaseID ' + + 'INNER JOIN Users ' + + 'ON Users.ID = PackageRequests.UsersID ' + + 'OR Users.ID = PackageBases.MaintainerUID ' + + 'WHERE PackageRequests.ID = ?', [reqid]) return [row[0] for row in cur.fetchall()] -def get_tu_vote_reminder_recipients(cur, vote_id): - cur.execute('SELECT ID FROM Users WHERE AccountTypeID = 2 ' + - 'EXCEPT SELECT Users.ID FROM Users ' + - 'INNER JOIN TU_Votes ' + - 'ON TU_Votes.UserID = Users.ID ' + - 'WHERE TU_Votes.VoteID = %s', [vote_id]) +def get_tu_vote_reminder_recipients(conn, vote_id): + cur = conn.execute('SELECT ID FROM Users WHERE AccountTypeID = 2 ' + + 'EXCEPT SELECT Users.ID FROM Users ' + + 'INNER JOIN TU_Votes ' + + 'ON TU_Votes.UserID = Users.ID ' + + 'WHERE TU_Votes.VoteID = ?', [vote_id]) return [row[0] for row in cur.fetchall()] -def get_comment(cur, comment_id): - cur.execute('SELECT Comments FROM PackageComments WHERE ID = %s', - [comment_id]) +def get_comment(conn, comment_id): + cur = conn.execute('SELECT Comments FROM PackageComments WHERE ID = ?', + [comment_id]) return cur.fetchone()[0] -def get_flagger_comment(cur, pkgbase_id): - cur.execute('SELECT FlaggerComment FROM PackageBases WHERE ID = %s', - [pkgbase_id]) +def get_flagger_comment(conn, pkgbase_id): + cur = conn.execute('SELECT FlaggerComment FROM PackageBases WHERE ID = ?', + [pkgbase_id]) return cur.fetchone()[0] -def get_request_comment(cur, reqid): - cur.execute('SELECT Comments FROM PackageRequests WHERE ID = %s', [reqid]) +def get_request_comment(conn, reqid): + cur = conn.execute('SELECT Comments FROM PackageRequests WHERE ID = ?', + [reqid]) return cur.fetchone()[0] -def get_request_closure_comment(cur, reqid): - cur.execute('SELECT ClosureComment FROM PackageRequests WHERE ID = %s', - [reqid]) +def get_request_closure_comment(conn, reqid): + cur = conn.execute('SELECT ClosureComment FROM PackageRequests ' + + 'WHERE ID = ?', [reqid]) return cur.fetchone()[0] -def send_resetkey(cur, uid): - cur.execute('SELECT UserName, Email, ResetKey FROM Users WHERE ID = %s', - [uid]) +def send_resetkey(conn, uid): + cur = conn.execute('SELECT UserName, Email, ResetKey FROM Users ' + + 'WHERE ID = ?', [uid]) username, to, resetkey = cur.fetchone() subject = 'AUR Password Reset' @@ -186,9 +183,9 @@ def send_resetkey(cur, uid): send_notification([to], subject, body, refs) -def welcome(cur, uid): - cur.execute('SELECT UserName, Email, ResetKey FROM Users WHERE ID = %s', - [uid]) +def welcome(conn, uid): + cur = conn.execute('SELECT UserName, Email, ResetKey FROM Users ' + + 'WHERE ID = ?', [uid]) username, to, resetkey = cur.fetchone() subject = 'Welcome to the Arch User Repository' @@ -201,11 +198,11 @@ def welcome(cur, uid): send_notification([to], subject, body, refs) -def comment(cur, uid, pkgbase_id, comment_id): - user = username_from_id(cur, uid) - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = get_comment_recipients(cur, pkgbase_id, uid) - text = get_comment(cur, comment_id) +def comment(conn, uid, pkgbase_id, comment_id): + user = username_from_id(conn, uid) + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = get_comment_recipients(conn, pkgbase_id, uid) + text = get_comment(conn, comment_id) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -224,10 +221,10 @@ def comment(cur, uid, pkgbase_id, comment_id): send_notification(to, subject, body, refs, headers) -def update(cur, uid, pkgbase_id): - user = username_from_id(cur, uid) - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = get_update_recipients(cur, pkgbase_id, uid) +def update(conn, uid, pkgbase_id): + user = username_from_id(conn, uid) + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = get_update_recipients(conn, pkgbase_id, uid) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -246,11 +243,11 @@ def update(cur, uid, pkgbase_id): send_notification(to, subject, body, refs, headers) -def flag(cur, uid, pkgbase_id): - user = username_from_id(cur, uid) - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = [get_maintainer_email(cur, pkgbase_id)] - text = get_flagger_comment(cur, pkgbase_id) +def flag(conn, uid, pkgbase_id): + user = username_from_id(conn, uid) + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = [get_maintainer_email(conn, pkgbase_id)] + text = get_flagger_comment(conn, pkgbase_id) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -265,10 +262,10 @@ def flag(cur, uid, pkgbase_id): send_notification(to, subject, body, refs) -def adopt(cur, pkgbase_id, uid): - user = username_from_id(cur, uid) - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = get_ownership_recipients(cur, pkgbase_id, uid) +def adopt(conn, pkgbase_id, uid): + user = username_from_id(conn, uid) + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = get_ownership_recipients(conn, pkgbase_id, uid) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -281,10 +278,10 @@ def adopt(cur, pkgbase_id, uid): send_notification(to, subject, body, refs) -def disown(cur, pkgbase_id, uid): - user = username_from_id(cur, uid) - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = get_ownership_recipients(cur, pkgbase_id, uid) +def disown(conn, pkgbase_id, uid): + user = username_from_id(conn, uid) + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = get_ownership_recipients(conn, pkgbase_id, uid) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -297,9 +294,9 @@ def disown(cur, pkgbase_id, uid): send_notification(to, subject, body, refs) -def comaintainer_add(cur, pkgbase_id, uid): - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = [get_user_email(cur, uid)] +def comaintainer_add(conn, pkgbase_id, uid): + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = [get_user_email(conn, uid)] pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -310,9 +307,9 @@ def comaintainer_add(cur, pkgbase_id, uid): send_notification(to, subject, body, refs) -def comaintainer_remove(cur, pkgbase_id, uid): - pkgbase = pkgbase_from_id(cur, pkgbase_id) - to = [get_user_email(cur, uid)] +def comaintainer_remove(conn, pkgbase_id, uid): + pkgbase = pkgbase_from_id(conn, pkgbase_id) + to = [get_user_email(conn, uid)] pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -324,12 +321,12 @@ def comaintainer_remove(cur, pkgbase_id, uid): send_notification(to, subject, body, refs) -def delete(cur, uid, old_pkgbase_id, new_pkgbase_id=None): - user = username_from_id(cur, uid) - old_pkgbase = pkgbase_from_id(cur, old_pkgbase_id) +def delete(conn, uid, old_pkgbase_id, new_pkgbase_id=None): + user = username_from_id(conn, uid) + old_pkgbase = pkgbase_from_id(conn, old_pkgbase_id) if new_pkgbase_id: - new_pkgbase = pkgbase_from_id(cur, new_pkgbase_id) - to = get_recipients(cur, old_pkgbase_id, uid) + new_pkgbase = pkgbase_from_id(conn, new_pkgbase_id) + to = get_recipients(conn, old_pkgbase_id, uid) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + old_pkgbase + '/' @@ -354,12 +351,12 @@ def delete(cur, uid, old_pkgbase_id, new_pkgbase_id=None): send_notification(to, subject, body, refs) -def request_open(cur, uid, reqid, reqtype, pkgbase_id, merge_into=None): - user = username_from_id(cur, uid) - pkgbase = pkgbase_from_id(cur, pkgbase_id) +def request_open(conn, uid, reqid, reqtype, pkgbase_id, merge_into=None): + user = username_from_id(conn, uid) + pkgbase = pkgbase_from_id(conn, pkgbase_id) to = [aur_request_ml] - cc = get_request_recipients(cur, reqid) - text = get_request_comment(cur, reqid) + cc = get_request_recipients(conn, reqid) + text = get_request_comment(conn, reqid) user_uri = aur_location + '/account/' + user + '/' pkgbase_uri = aur_location + '/pkgbase/' + pkgbase + '/' @@ -388,14 +385,14 @@ def request_open(cur, uid, reqid, reqtype, pkgbase_id, merge_into=None): send_notification(to, subject, body, refs, headers) -def request_close(cur, uid, reqid, reason): +def request_close(conn, uid, reqid, reason): to = [aur_request_ml] - cc = get_request_recipients(cur, reqid) - text = get_request_closure_comment(cur, reqid) + cc = get_request_recipients(conn, reqid) + text = get_request_closure_comment(conn, reqid) subject = '[PRQ#%d] Request %s' % (int(reqid), reason.title()) if int(uid): - user = username_from_id(cur, uid) + user = username_from_id(conn, uid) user_uri = aur_location + '/account/' + user + '/' body = 'Request #%d has been %s by %s [1]' % (int(reqid), reason, user) refs = '[1] ' + user_uri @@ -414,8 +411,8 @@ def request_close(cur, uid, reqid, reason): send_notification(to, subject, body, refs, headers) -def tu_vote_reminder(cur, vote_id): - to = get_tu_vote_reminder_recipients(cur, vote_id) +def tu_vote_reminder(conn, vote_id): + to = get_tu_vote_reminder_recipients(conn, vote_id) vote_uri = aur_location + '/tu/?id=' + vote_id @@ -445,15 +442,12 @@ def main(): 'tu-vote-reminder': tu_vote_reminder, } - db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) - cur = db.cursor() + conn = aurweb.db.Connection() - action_map[action](cur, *sys.argv[2:]) + action_map[action](conn, *sys.argv[2:]) - db.commit() - db.close() + conn.commit() + conn.close() if __name__ == '__main__': diff --git a/scripts/pkgmaint.py b/scripts/pkgmaint.py index 346b046..d0f8fe7 100755 --- a/scripts/pkgmaint.py +++ b/scripts/pkgmaint.py @@ -1,31 +1,17 @@ #!/usr/bin/python3 -import configparser -import mysql.connector -import os - -config = configparser.RawConfigParser() -config.read(os.path.dirname(os.path.realpath(__file__)) + "/../conf/config") - -aur_db_host = config.get('database', 'host') -aur_db_name = config.get('database', 'name') -aur_db_user = config.get('database', 'user') -aur_db_pass = config.get('database', 'password') -aur_db_socket = config.get('database', 'socket') +import aurweb.db def main(): - db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) - cur = db.cursor() + conn = aurweb.db.Connection() - cur.execute("DELETE FROM PackageBases WHERE " + - "UNIX_TIMESTAMP() - SubmittedTS > 86400 " + - "AND PackagerUID IS NULL") + conn.execute("DELETE FROM PackageBases WHERE " + + "UNIX_TIMESTAMP() - SubmittedTS > 86400 " + + "AND PackagerUID IS NULL") - db.commit() - db.close() + conn.commit() + conn.close() if __name__ == '__main__': diff --git a/scripts/popupdate.py b/scripts/popupdate.py index 26d8379..f5e09d9 100755 --- a/scripts/popupdate.py +++ b/scripts/popupdate.py @@ -1,36 +1,22 @@ #!/usr/bin/python3 -import configparser -import mysql.connector -import os +import aurweb.db -config = configparser.RawConfigParser() -config.read(os.path.dirname(os.path.realpath(__file__)) + "/../conf/config") -aur_db_host = config.get('database', 'host') -aur_db_name = config.get('database', 'name') -aur_db_user = config.get('database', 'user') -aur_db_pass = config.get('database', 'password') -aur_db_socket = config.get('database', 'socket') +def main(): + conn = aurweb.db.Connection() + conn.execute("UPDATE PackageBases SET NumVotes = (" + + "SELECT COUNT(*) FROM PackageVotes " + + "WHERE PackageVotes.PackageBaseID = PackageBases.ID)") -def main(): - db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) - cur = db.cursor() - - cur.execute("UPDATE PackageBases SET NumVotes = (" + - "SELECT COUNT(*) FROM PackageVotes " + - "WHERE PackageVotes.PackageBaseID = PackageBases.ID)") - - cur.execute("UPDATE PackageBases SET Popularity = (" + - "SELECT COALESCE(SUM(POWER(0.98, (UNIX_TIMESTAMP() - VoteTS) / 86400)), 0.0) " + - "FROM PackageVotes WHERE PackageVotes.PackageBaseID = " + - "PackageBases.ID AND NOT VoteTS IS NULL)") - - db.commit() - db.close() + conn.execute("UPDATE PackageBases SET Popularity = (" + + "SELECT COALESCE(SUM(POWER(0.98, (UNIX_TIMESTAMP() - VoteTS) / 86400)), 0.0) " + + "FROM PackageVotes WHERE PackageVotes.PackageBaseID = " + + "PackageBases.ID AND NOT VoteTS IS NULL)") + + conn.commit() + conn.close() if __name__ == '__main__': diff --git a/scripts/tuvotereminder.py b/scripts/tuvotereminder.py index dc16397..a053608 100755 --- a/scripts/tuvotereminder.py +++ b/scripts/tuvotereminder.py @@ -1,34 +1,24 @@ #!/usr/bin/python3 -import configparser -import mysql.connector -import os import subprocess import time -config = configparser.RawConfigParser() -config.read(os.path.dirname(os.path.realpath(__file__)) + "/../conf/config") +import aurweb.config +import aurweb.db -aur_db_host = config.get('database', 'host') -aur_db_name = config.get('database', 'name') -aur_db_user = config.get('database', 'user') -aur_db_pass = config.get('database', 'password') -aur_db_socket = config.get('database', 'socket') -notify_cmd = config.get('notifications', 'notify-cmd') +notify_cmd = aurweb.config.get('notifications', 'notify-cmd') def main(): - db = mysql.connector.connect(host=aur_db_host, user=aur_db_user, - passwd=aur_db_pass, db=aur_db_name, - unix_socket=aur_db_socket, buffered=True) - cur = db.cursor() + conn = aurweb.db.Connection() now = int(time.time()) filter_from = now + 500 filter_to = now + 172800 - cur.execute("SELECT ID FROM TU_VoteInfo WHERE End >= %s AND End <= %s", - [filter_from, filter_to]) + cur = conn.execute("SELECT ID FROM TU_VoteInfo " + + "WHERE End >= ? AND End <= ?", + [filter_from, filter_to]) for vote_id in [row[0] for row in cur.fetchall()]: subprocess.Popen((notify_cmd, 'tu-vote-reminder', str(vote_id))) -- 2.10.0
Determine the top-level directory before running tests and make all script paths relative to that directory. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- git-interface/test/setup.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/git-interface/test/setup.sh b/git-interface/test/setup.sh index d269af6..0995f05 100644 --- a/git-interface/test/setup.sh +++ b/git-interface/test/setup.sh @@ -1,15 +1,16 @@ TEST_DIRECTORY="$(pwd)" +TOPLEVEL="$(cd ../.. && pwd)" . ./sharness.sh # Configure python search path. -PYTHONPATH="$TEST_DIRECTORY/../../" +PYTHONPATH="$TOPLEVEL" export PYTHONPATH # Configure paths to the Git interface scripts. -GIT_AUTH="$TEST_DIRECTORY/../git-auth.py" -GIT_SERVE="$TEST_DIRECTORY/../git-serve.py" -GIT_UPDATE="$TEST_DIRECTORY/../git-update.py" +GIT_AUTH="$TOPLEVEL/git-interface/git-auth.py" +GIT_SERVE="$TOPLEVEL/git-interface/git-serve.py" +GIT_UPDATE="$TOPLEVEL/git-interface/git-update.py" # Create the configuration file and a dummy notification script. cat >config <<-EOF @@ -86,7 +87,7 @@ sed \ -e 's/ ENGINE = InnoDB//' \ -e 's/ [A-Z]* UNSIGNED NOT NULL AUTO_INCREMENT/ INTEGER NOT NULL/' \ -e 's/([0-9, ]*) UNSIGNED / UNSIGNED /' \ - "$TEST_DIRECTORY/../../schema/aur-schema.sql" | sqlite3 aur.db + "$TOPLEVEL/schema/aur-schema.sql" | sqlite3 aur.db echo "INSERT INTO Users (ID, UserName, Passwd, Email, AccountTypeID) VALUES (1, 'user', '!', 'user@localhost', 1);" | sqlite3 aur.db echo "INSERT INTO Users (ID, UserName, Passwd, Email, AccountTypeID) VALUES (2, 'tu', '!', 'tu@localhost', 2);" | sqlite3 aur.db -- 2.10.0
Move and rename the existing git-interface tests such that tests for other scripts can be added easily. In particular, the following changes are made: * Move the existing tests from git-interface/test/ to test/. * Rename t0001-auth.sh to t1100-git-auth.sh. * Rename t0002-serve.sh to t1200-git-serve.sh. * Rename t0003-update.sh to t1300-git-update.sh. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- {git-interface/test => test}/Makefile | 0 {git-interface/test => test}/setup.sh | 2 +- {git-interface/test => test}/sharness.sh | 0 git-interface/test/t0001-auth.sh => test/t1100-git-auth.sh | 0 git-interface/test/t0002-serve.sh => test/t1200-git-serve.sh | 0 git-interface/test/t0003-update.sh => test/t1300-git-update.sh | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename {git-interface/test => test}/Makefile (100%) rename {git-interface/test => test}/setup.sh (99%) rename {git-interface/test => test}/sharness.sh (100%) rename git-interface/test/t0001-auth.sh => test/t1100-git-auth.sh (100%) rename git-interface/test/t0002-serve.sh => test/t1200-git-serve.sh (100%) rename git-interface/test/t0003-update.sh => test/t1300-git-update.sh (100%) diff --git a/git-interface/test/Makefile b/test/Makefile similarity index 100% rename from git-interface/test/Makefile rename to test/Makefile diff --git a/git-interface/test/setup.sh b/test/setup.sh similarity index 99% rename from git-interface/test/setup.sh rename to test/setup.sh index 0995f05..232b14d 100644 --- a/git-interface/test/setup.sh +++ b/test/setup.sh @@ -1,5 +1,5 @@ TEST_DIRECTORY="$(pwd)" -TOPLEVEL="$(cd ../.. && pwd)" +TOPLEVEL="$(cd .. && pwd)" . ./sharness.sh diff --git a/git-interface/test/sharness.sh b/test/sharness.sh similarity index 100% rename from git-interface/test/sharness.sh rename to test/sharness.sh diff --git a/git-interface/test/t0001-auth.sh b/test/t1100-git-auth.sh similarity index 100% rename from git-interface/test/t0001-auth.sh rename to test/t1100-git-auth.sh diff --git a/git-interface/test/t0002-serve.sh b/test/t1200-git-serve.sh similarity index 100% rename from git-interface/test/t0002-serve.sh rename to test/t1200-git-serve.sh diff --git a/git-interface/test/t0003-update.sh b/test/t1300-git-update.sh similarity index 100% rename from git-interface/test/t0003-update.sh rename to test/t1300-git-update.sh -- 2.10.0
Add information on the new directory layout. Shared Python modules and tests now have their own subdirectories. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README b/README index 5ab84ab..c110ef8 100644 --- a/README +++ b/README @@ -17,6 +17,9 @@ The aurweb project includes Directory Layout ---------------- +aurweb:: + Shared aurweb Python modules. + conf:: Configuration and configuration templates. @@ -35,6 +38,9 @@ schema:: scripts:: Scripts for AUR maintenance. +test:: + Test suite and test cases. + upgrading:: Instructions for upgrading setups from one release to another. -- 2.10.0
Instead of writing the output to hardcoded files (relative to the document root), make the output paths of mkpkglists configurable. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- conf/config.proto | 4 ++++ scripts/mkpkglists.py | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/conf/config.proto b/conf/config.proto index c56141c..e545977 100644 --- a/conf/config.proto +++ b/conf/config.proto @@ -63,3 +63,7 @@ max-blob-size = 256000 db-path = /srv/http/aurweb/aurblup/ sync-dbs = core extra community multilib testing community-testing servers = ftp://mirrors.kernel.org/archlinux/%s/os/x86_64 + +[mkpkglists] +packagesfile = /srv/http/aurweb/web/html/packages.gz +pkgbasefile = /srv/http/aurweb/web/html/pkgbase.gz diff --git a/scripts/mkpkglists.py b/scripts/mkpkglists.py index 70cbd13..8a0f2e9 100755 --- a/scripts/mkpkglists.py +++ b/scripts/mkpkglists.py @@ -2,11 +2,12 @@ import datetime import gzip -import os +import aurweb.config import aurweb.db -docroot = os.path.dirname(os.path.realpath(__file__)) + "/../web/html/" +packagesfile = aurweb.config.get('mkpkglists', 'packagesfile') +pkgbasefile = aurweb.config.get('mkpkglists', 'pkgbasefile') def main(): @@ -16,7 +17,7 @@ def main(): pkglist_header = "# AUR package list, generated on " + datestr pkgbaselist_header = "# AUR package base list, generated on " + datestr - with gzip.open(docroot + "packages.gz", "w") as f: + with gzip.open(packagesfile, "w") as f: f.write(bytes(pkglist_header + "\n", "UTF-8")) cur = conn.execute("SELECT Packages.Name FROM Packages " + "INNER JOIN PackageBases " + @@ -24,7 +25,7 @@ def main(): "WHERE PackageBases.PackagerUID IS NOT NULL") f.writelines([bytes(x[0] + "\n", "UTF-8") for x in cur.fetchall()]) - with gzip.open(docroot + "pkgbase.gz", "w") as f: + with gzip.open(pkgbasefile, "w") as f: f.write(bytes(pkgbaselist_header + "\n", "UTF-8")) cur = conn.execute("SELECT Name FROM PackageBases " + "WHERE PackagerUID IS NOT NULL") -- 2.10.0
Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- test/setup.sh | 5 +++++ test/t2100-mkpkglists.sh | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100755 test/t2100-mkpkglists.sh diff --git a/test/setup.sh b/test/setup.sh index 232b14d..85faba0 100644 --- a/test/setup.sh +++ b/test/setup.sh @@ -11,6 +11,7 @@ export PYTHONPATH GIT_AUTH="$TOPLEVEL/git-interface/git-auth.py" GIT_SERVE="$TOPLEVEL/git-interface/git-serve.py" GIT_UPDATE="$TOPLEVEL/git-interface/git-update.py" +MKPKGLISTS="$TOPLEVEL/scripts/mkpkglists.py" # Create the configuration file and a dummy notification script. cat >config <<-EOF @@ -40,6 +41,10 @@ ssh-cmdline = ssh aur@aur.archlinux.org [update] max-blob-size = 256000 + +[mkpkglists] +packagesfile = packages.gz +pkgbasefile = pkgbase.gz EOF cat >notify.sh <<-EOF diff --git a/test/t2100-mkpkglists.sh b/test/t2100-mkpkglists.sh new file mode 100755 index 0000000..a84a1b6 --- /dev/null +++ b/test/t2100-mkpkglists.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +test_description='mkpkglists tests' + +. ./setup.sh + +test_expect_success 'Test package list generation with no packages.' ' + echo "DELETE FROM Packages;" | sqlite3 aur.db && + echo "DELETE FROM PackageBases;" | sqlite3 aur.db && + "$MKPKGLISTS" && + test $(zcat packages.gz | wc -l) -eq 1 && + test $(zcat pkgbase.gz | wc -l) -eq 1 +' + +test_expect_success 'Test package list generation.' ' + cat <<-EOD | sqlite3 aur.db && + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (1, "foobar", 1, 0, 0); + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (2, "foobar2", 2, 0, 0); + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (3, "foobar3", NULL, 0, 0); + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (4, "foobar4", 1, 0, 0); + INSERT INTO Packages (ID, PackageBaseID, Name) VALUES (1, 1, "pkg1"); + INSERT INTO Packages (ID, PackageBaseID, Name) VALUES (2, 1, "pkg2"); + INSERT INTO Packages (ID, PackageBaseID, Name) VALUES (3, 1, "pkg3"); + INSERT INTO Packages (ID, PackageBaseID, Name) VALUES (4, 2, "pkg4"); + INSERT INTO Packages (ID, PackageBaseID, Name) VALUES (5, 3, "pkg5"); + EOD + "$MKPKGLISTS" && + cat <<-EOD >expected && + foobar + foobar2 + foobar4 + EOD + gunzip pkgbase.gz && + sed "/^#/d" pkgbase >actual && + test_cmp actual expected && + cat <<-EOD >expected && + pkg1 + pkg2 + pkg3 + pkg4 + EOD + gunzip packages.gz && + sed "/^#/d" packages >actual && + test_cmp actual expected +' + +test_done -- 2.10.0
Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- test/setup.sh | 4 +++- test/t2200-tuvotereminder.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 test/t2200-tuvotereminder.sh diff --git a/test/setup.sh b/test/setup.sh index 85faba0..e6a9a16 100644 --- a/test/setup.sh +++ b/test/setup.sh @@ -12,6 +12,7 @@ GIT_AUTH="$TOPLEVEL/git-interface/git-auth.py" GIT_SERVE="$TOPLEVEL/git-interface/git-serve.py" GIT_UPDATE="$TOPLEVEL/git-interface/git-update.py" MKPKGLISTS="$TOPLEVEL/scripts/mkpkglists.py" +TUVOTEREMINDER="$TOPLEVEL/scripts/tuvotereminder.py" # Create the configuration file and a dummy notification script. cat >config <<-EOF @@ -47,8 +48,9 @@ packagesfile = packages.gz pkgbasefile = pkgbase.gz EOF -cat >notify.sh <<-EOF +cat >notify.sh <<-\EOF #!/bin/sh +echo $* >>notify.out EOF chmod +x notify.sh diff --git a/test/t2200-tuvotereminder.sh b/test/t2200-tuvotereminder.sh new file mode 100755 index 0000000..438c0c3 --- /dev/null +++ b/test/t2200-tuvotereminder.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='tuvotereminder tests' + +. ./setup.sh + +test_expect_success 'Test Trusted User vote reminders.' ' + now=$(date -d now +%s) && + tomorrow=$(date -d tomorrow +%s) && + threedays=$(date -d "3 days" +%s) && + cat <<-EOD | sqlite3 aur.db && + INSERT INTO TU_VoteInfo (ID, Agenda, User, Submitted, End, Quorum, SubmitterID) VALUES (1, "Lorem ipsum.", "user", 0, $now, 0.00, 2); + INSERT INTO TU_VoteInfo (ID, Agenda, User, Submitted, End, Quorum, SubmitterID) VALUES (2, "Lorem ipsum.", "user", 0, $tomorrow, 0.00, 2); + INSERT INTO TU_VoteInfo (ID, Agenda, User, Submitted, End, Quorum, SubmitterID) VALUES (3, "Lorem ipsum.", "user", 0, $tomorrow, 0.00, 2); + INSERT INTO TU_VoteInfo (ID, Agenda, User, Submitted, End, Quorum, SubmitterID) VALUES (4, "Lorem ipsum.", "user", 0, $threedays, 0.00, 2); + EOD + >notify.out && + "$TUVOTEREMINDER" && + cat <<-EOD >expected && + tu-vote-reminder 2 + tu-vote-reminder 3 + EOD + test_cmp notify.out expected +' + +test_done -- 2.10.0
Avoid using UNIX_TIMESTAMP which is not part of the SQL standard. See f2a6bd2 (git-interface: Do not use UNIX_TIMESTAMP, 2016-08-05) for related changes. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- scripts/pkgmaint.py | 6 ++++-- scripts/popupdate.py | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/pkgmaint.py b/scripts/pkgmaint.py index d0f8fe7..3ad9ed8 100755 --- a/scripts/pkgmaint.py +++ b/scripts/pkgmaint.py @@ -1,14 +1,16 @@ #!/usr/bin/python3 +import time + import aurweb.db def main(): conn = aurweb.db.Connection() + limit_to = int(time.time()) - 86400 conn.execute("DELETE FROM PackageBases WHERE " + - "UNIX_TIMESTAMP() - SubmittedTS > 86400 " + - "AND PackagerUID IS NULL") + "SubmittedTS < ? AND PackagerUID IS NULL", [limit_to]) conn.commit() conn.close() diff --git a/scripts/popupdate.py b/scripts/popupdate.py index f5e09d9..58cd018 100755 --- a/scripts/popupdate.py +++ b/scripts/popupdate.py @@ -1,5 +1,7 @@ #!/usr/bin/python3 +import time + import aurweb.db @@ -10,10 +12,11 @@ def main(): "SELECT COUNT(*) FROM PackageVotes " + "WHERE PackageVotes.PackageBaseID = PackageBases.ID)") + now = int(time.time()) conn.execute("UPDATE PackageBases SET Popularity = (" + - "SELECT COALESCE(SUM(POWER(0.98, (UNIX_TIMESTAMP() - VoteTS) / 86400)), 0.0) " + + "SELECT COALESCE(SUM(POWER(0.98, (? - VoteTS) / 86400)), 0.0) " + "FROM PackageVotes WHERE PackageVotes.PackageBaseID = " + - "PackageBases.ID AND NOT VoteTS IS NULL)") + "PackageBases.ID AND NOT VoteTS IS NULL)", [now]) conn.commit() conn.close() -- 2.10.0
Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- test/setup.sh | 1 + test/t2300-pkgmaint.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100755 test/t2300-pkgmaint.sh diff --git a/test/setup.sh b/test/setup.sh index e6a9a16..622aab0 100644 --- a/test/setup.sh +++ b/test/setup.sh @@ -13,6 +13,7 @@ GIT_SERVE="$TOPLEVEL/git-interface/git-serve.py" GIT_UPDATE="$TOPLEVEL/git-interface/git-update.py" MKPKGLISTS="$TOPLEVEL/scripts/mkpkglists.py" TUVOTEREMINDER="$TOPLEVEL/scripts/tuvotereminder.py" +PKGMAINT="$TOPLEVEL/scripts/pkgmaint.py" # Create the configuration file and a dummy notification script. cat >config <<-EOF diff --git a/test/t2300-pkgmaint.sh b/test/t2300-pkgmaint.sh new file mode 100755 index 0000000..5c55aaf --- /dev/null +++ b/test/t2300-pkgmaint.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='pkgmaint tests' + +. ./setup.sh + +test_expect_success 'Test package base cleanup script.' ' + now=$(date -d now +%s) && + threedaysago=$(date -d "3 days ago" +%s) && + cat <<-EOD | sqlite3 aur.db && + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (1, "foobar", 1, $now, 0); + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (2, "foobar2", 2, $threedaysago, 0); + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (3, "foobar3", NULL, $now, 0); + INSERT INTO PackageBases (ID, Name, PackagerUID, SubmittedTS, ModifiedTS) VALUES (4, "foobar4", NULL, $threedaysago, 0); + EOD + "$PKGMAINT" && + cat <<-EOD >expected && + foobar + foobar2 + foobar3 + EOD + echo "SELECT Name FROM PackageBases;" | sqlite3 aur.db >actual && + test_cmp actual expected +' + +test_done -- 2.10.0
Support for multiple servers has never been used by the official aurweb setup and the current implementation makes it impossible to use server URIs that contain spaces. For simplicity, change the implementation such that only a single server is supported. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- conf/config.proto | 2 +- scripts/aurblup.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/config.proto b/conf/config.proto index e545977..21441a9 100644 --- a/conf/config.proto +++ b/conf/config.proto @@ -62,7 +62,7 @@ max-blob-size = 256000 [aurblup] db-path = /srv/http/aurweb/aurblup/ sync-dbs = core extra community multilib testing community-testing -servers = ftp://mirrors.kernel.org/archlinux/%s/os/x86_64 +server = ftp://mirrors.kernel.org/archlinux/%s/os/x86_64 [mkpkglists] packagesfile = /srv/http/aurweb/web/html/packages.gz diff --git a/scripts/aurblup.py b/scripts/aurblup.py index 0009715..1b6de2f 100755 --- a/scripts/aurblup.py +++ b/scripts/aurblup.py @@ -8,7 +8,7 @@ import aurweb.db db_path = aurweb.config.get('aurblup', 'db-path') sync_dbs = aurweb.config.get('aurblup', 'sync-dbs').split(' ') -servers = aurweb.config.get('aurblup', 'servers').split(' ') +server = aurweb.config.get('aurblup', 'server') def main(): @@ -19,7 +19,7 @@ def main(): h = pyalpm.Handle("/", db_path) for sync_db in sync_dbs: repo = h.register_syncdb(sync_db, pyalpm.SIG_DATABASE_OPTIONAL) - repo.servers = [server.replace("%s", sync_db) for server in servers] + repo.servers = [server.replace("%s", sync_db)] t = h.init_transaction() repo.update(False) t.release() -- 2.10.0
Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org> --- test/setup.sh | 6 ++++++ test/t2400-aurblup.sh | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100755 test/t2400-aurblup.sh diff --git a/test/setup.sh b/test/setup.sh index 622aab0..e379ada 100644 --- a/test/setup.sh +++ b/test/setup.sh @@ -14,6 +14,7 @@ GIT_UPDATE="$TOPLEVEL/git-interface/git-update.py" MKPKGLISTS="$TOPLEVEL/scripts/mkpkglists.py" TUVOTEREMINDER="$TOPLEVEL/scripts/tuvotereminder.py" PKGMAINT="$TOPLEVEL/scripts/pkgmaint.py" +AURBLUP="$TOPLEVEL/scripts/aurblup.py" # Create the configuration file and a dummy notification script. cat >config <<-EOF @@ -44,6 +45,11 @@ ssh-cmdline = ssh aur@aur.archlinux.org [update] max-blob-size = 256000 +[aurblup] +db-path = $(pwd)/sync/ +sync-dbs = test +server = file://$(pwd)/remote/ + [mkpkglists] packagesfile = packages.gz pkgbasefile = pkgbase.gz diff --git a/test/t2400-aurblup.sh b/test/t2400-aurblup.sh new file mode 100755 index 0000000..708281c --- /dev/null +++ b/test/t2400-aurblup.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +test_description='aurblup tests' + +. ./setup.sh + +test_expect_success 'Test official provider update script.' ' + mkdir -p remote/test/foobar-1.0-1 && + cat <<-EOD >remote/test/foobar-1.0-1/desc && + %FILENAME% + foobar-1.0-any.pkg.tar.xz + + %NAME% + foobar + + %VERSION% + 1.0-1 + + %ARCH% + any + EOD + mkdir -p remote/test/foobar2-1.0-1 && + cat <<-EOD >remote/test/foobar2-1.0-1/desc && + %FILENAME% + foobar2-1.0-any.pkg.tar.xz + + %NAME% + foobar2 + + %VERSION% + 1.0-1 + + %ARCH% + any + + %PROVIDES% + foobar3 + foobar4 + EOD + ( cd remote/test && bsdtar -czf ../test.db * ) && + mkdir sync && + "$AURBLUP" && + cat <<-EOD >expected && + foobar|test|foobar + foobar2|test|foobar2 + foobar2|test|foobar3 + foobar2|test|foobar4 + EOD + echo "SELECT Name, Repo, Provides FROM OfficialProviders ORDER BY Provides;" | sqlite3 aur.db >actual && + test_cmp actual expected +' + +test_done -- 2.10.0
participants (1)
-
Lukas Fleischer