12 repo_path
= config
.get('serve', 'repo-path')
13 repo_regex
= config
.get('serve', 'repo-regex')
14 git_shell_cmd
= config
.get('serve', 'git-shell-cmd')
15 git_update_cmd
= config
.get('serve', 'git-update-cmd')
16 ssh_cmdline
= config
.get('serve', 'ssh-cmdline')
18 enable_maintenance
= config
.getboolean('options', 'enable-maintenance')
19 maintenance_exc
= config
.get('options', 'maintenance-exceptions').split()
22 def pkgbase_from_name(pkgbase
):
23 conn
= db
.Connection()
24 cur
= conn
.execute("SELECT ID FROM PackageBases WHERE Name = ?", [pkgbase
])
27 return row
[0] if row
else None
30 def pkgbase_exists(pkgbase
):
31 return pkgbase_from_name(pkgbase
) is not None
35 conn
= db
.Connection()
37 cur
= conn
.execute("SELECT ID FROM Users WHERE Username = ?", [user
])
38 userid
= cur
.fetchone()[0]
40 die('{:s}: unknown user: {:s}'.format(action
, user
))
42 cur
= conn
.execute("SELECT Name, PackagerUID FROM PackageBases " +
43 "WHERE MaintainerUID = ?", [userid
])
45 print((' ' if row
[1] else '*') + row
[0])
49 def create_pkgbase(pkgbase
, user
):
50 if not re
.match(repo_regex
, pkgbase
):
51 die('{:s}: invalid repository name: {:s}'.format(action
, pkgbase
))
52 if pkgbase_exists(pkgbase
):
53 die('{:s}: package base already exists: {:s}'.format(action
, pkgbase
))
55 conn
= db
.Connection()
57 cur
= conn
.execute("SELECT ID FROM Users WHERE Username = ?", [user
])
58 userid
= cur
.fetchone()[0]
60 die('{:s}: unknown user: {:s}'.format(action
, user
))
62 now
= int(time
.time())
63 cur
= conn
.execute("INSERT INTO PackageBases (Name, SubmittedTS, " +
64 "ModifiedTS, SubmitterUID, MaintainerUID) VALUES " +
65 "(?, ?, ?, ?, ?)", [pkgbase
, now
, now
, userid
, userid
])
66 pkgbase_id
= cur
.lastrowid
68 cur
= conn
.execute("INSERT INTO PackageNotifications " +
69 "(PackageBaseID, UserID) VALUES (?, ?)",
76 def pkgbase_set_keywords(pkgbase
, keywords
):
77 pkgbase_id
= pkgbase_from_name(pkgbase
)
79 die('{:s}: package base not found: {:s}'.format(action
, pkgbase
))
81 conn
= db
.Connection()
83 conn
.execute("DELETE FROM PackageKeywords WHERE PackageBaseID = ?",
85 for keyword
in keywords
:
86 conn
.execute("INSERT INTO PackageKeywords (PackageBaseID, Keyword) " +
87 "VALUES (?, ?)", [pkgbase_id
, keyword
])
93 def pkgbase_has_write_access(pkgbase
, user
):
94 conn
= db
.Connection()
96 cur
= conn
.execute("SELECT COUNT(*) FROM PackageBases " +
97 "LEFT JOIN PackageComaintainers " +
98 "ON PackageComaintainers.PackageBaseID = PackageBases.ID " +
100 "ON Users.ID = PackageBases.MaintainerUID " +
101 "OR PackageBases.MaintainerUID IS NULL " +
102 "OR Users.ID = PackageComaintainers.UsersID " +
103 "WHERE Name = ? AND Username = ?", [pkgbase
, user
])
104 return cur
.fetchone()[0] > 0
108 sys
.stderr
.write("{:s}\n".format(msg
))
112 def die_with_help(msg
):
113 die(msg
+ "\nTry `{:s} help` for a list of commands.".format(ssh_cmdline
))
117 sys
.stderr
.write("warning: {:s}\n".format(msg
))
120 user
= os
.environ
.get('AUR_USER')
121 privileged
= (os
.environ
.get('AUR_PRIVILEGED', '0') == '1')
122 ssh_cmd
= os
.environ
.get('SSH_ORIGINAL_COMMAND')
123 ssh_client
= os
.environ
.get('SSH_CLIENT')
126 die_with_help("Interactive shell is disabled.")
127 cmdargv
= shlex
.split(ssh_cmd
)
129 remote_addr
= ssh_client
.split(' ')[0] if ssh_client
else None
131 if enable_maintenance
:
132 if remote_addr
not in maintenance_exc
:
133 die("The AUR is down due to maintenance. We will be back soon.")
135 if action
== 'git-upload-pack' or action
== 'git-receive-pack':
137 die_with_help("{:s}: missing path".format(action
))
139 path
= cmdargv
[1].rstrip('/')
140 if not path
.startswith('/'):
142 if not path
.endswith('.git'):
145 if not re
.match(repo_regex
, pkgbase
):
146 die('{:s}: invalid repository name: {:s}'.format(action
, pkgbase
))
148 if action
== 'git-receive-pack' and pkgbase_exists(pkgbase
):
149 if not privileged
and not pkgbase_has_write_access(pkgbase
, user
):
150 die('{:s}: permission denied: {:s}'.format(action
, user
))
152 os
.environ
["AUR_USER"] = user
153 os
.environ
["AUR_PKGBASE"] = pkgbase
154 os
.environ
["GIT_NAMESPACE"] = pkgbase
155 cmd
= action
+ " '" + repo_path
+ "'"
156 os
.execl(git_shell_cmd
, git_shell_cmd
, '-c', cmd
)
157 elif action
== 'set-keywords':
159 die_with_help("{:s}: missing repository name".format(action
))
160 pkgbase_set_keywords(cmdargv
[1], cmdargv
[2:])
161 elif action
== 'list-repos':
163 die_with_help("{:s}: too many arguments".format(action
))
165 elif action
== 'setup-repo':
167 die_with_help("{:s}: missing repository name".format(action
))
169 die_with_help("{:s}: too many arguments".format(action
))
170 warn('{:s} is deprecated. Use `git push` to create new repositories.'.format(action
))
171 create_pkgbase(cmdargv
[1], user
)
172 elif action
== 'restore':
174 die_with_help("{:s}: missing repository name".format(action
))
176 die_with_help("{:s}: too many arguments".format(action
))
179 if not re
.match(repo_regex
, pkgbase
):
180 die('{:s}: invalid repository name: {:s}'.format(action
, pkgbase
))
182 if pkgbase_exists(pkgbase
):
183 die('{:s}: package base exists: {:s}'.format(action
, pkgbase
))
184 create_pkgbase(pkgbase
, user
)
186 os
.environ
["AUR_USER"] = user
187 os
.environ
["AUR_PKGBASE"] = pkgbase
188 os
.execl(git_update_cmd
, git_update_cmd
, 'restore')
189 elif action
== 'help':
191 " help Show this help message and exit.\n" +
192 " list-repos List all your repositories.\n" +
193 " restore <name> Restore a deleted package base.\n" +
194 " set-keywords <name> [...] Change package base keywords.\n" +
195 " setup-repo <name> Create an empty repository.\n" +
196 " git-receive-pack Internal command used with Git.\n" +
197 " git-upload-pack Internal command used with Git.")
199 die_with_help("invalid command: {:s}".format(action
))