1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
import argparse
import logging
import os
import pygit2
import re
from subprocess import CalledProcessError
import sys
from gitubuntu.__main__ import top_level_defaults
from gitubuntu.git_repository import (
GitUbuntuRepository,
GitUbuntuRepositoryFetchError,
GitUbuntuChangelogError,
)
from gitubuntu.run import decode_binary, run
def parse_args(subparsers=None, base_subparsers=None):
kwargs = dict(
description='Add a launchpad user\'s repository as a remote',
formatter_class=argparse.RawTextHelpFormatter)
if base_subparsers:
kwargs['parents'] = base_subparsers
if subparsers:
parser = subparsers.add_parser('remote', **kwargs)
parser.set_defaults(func=cli_main)
else:
parser = argparse.ArgumentParser(**kwargs)
known_subcommands = {
'add': 'Add a launchpad user\'s repository as a remote',
}
subsubparsers = parser.add_subparsers(
dest='subsubcommand',
help='',
# this will look off until more than one subcommand exists
metavar='%s' % '|'.join(sorted(known_subcommands.keys())),
)
add_parser = subsubparsers.add_parser(
'add',
help=known_subcommands['add']
)
add_parser.add_argument(
'user',
type=str,
help="Launchpad user to add as a remote. If 'debian', parse "
"pkg/ubuntu/devel:debian/control for either "
"X-Debian-Vcs-Git or Vcs-Git. If found, add it as a remote "
"named 'debian'.",
)
add_parser.add_argument(
'url',
type=str,
help="Specify URL to add as a remote. If not specified, a URL is "
"derived from USER and the repository source package.",
default=None,
nargs='?',
)
add_parser.add_argument(
'--directory',
type=str,
help="Local git directory to modify. If not specified, the "
"current directory is assumed.",
)
add_parser.add_argument(
'-l', '--lp-user',
type=str,
help=argparse.SUPPRESS
)
add_parser.add_argument(
'-r', '--remote-name',
type=str,
help="Specify remote name. If not specified the remote will be "
"named after the user argument.",
)
add_parser.add_argument(
'--no-fetch',
action='store_true',
help="Do not fetch the remote after adding",
)
add_parser.add_argument(
'--package',
type=str,
help="Specify the source package rather than automatically "
"determining it from debian/changelog.",
)
if not subparsers:
return parser.parse_args()
return "remote - %s" % kwargs['description']
def cli_main(args):
if args.directory is not None:
directory = os.path.abspath(args.directory)
else:
directory = os.getcwd()
return main(
args.subsubcommand,
args.user,
args.package,
args.url,
args.lp_user,
directory,
args.remote_name,
args.no_fetch,
args.proto,
)
def do_add_debian(repo, package, no_fetch=False):
"""add a Debian remote to a repository
Parses debian/control in pkg/ubuntu/devel, and uses the value of:
1) X-Debian-Vcs-Git
or
2) Vcs-Git, only if there is no X-Debian-Vcs-Git
as the URL for a remote named Debian.
@repo: GitUbuntuRepository to modify
@package: source package name (XXX: is this derive-able from @repo?)
@no_fetch: if True, do not fetch the remote after adding it
"""
remote_name = 'debian'
control_file = None
try:
control_file = repo.extract_file_from_treeish(
treeish_string='pkg/ubuntu/devel',
filename='debian/control',
)
control_file.seek(0)
x_debian_vcs_git = None
vcs_git = None
for line in control_file:
line = decode_binary(line)
if line.startswith('X-Debian-Vcs-Git:'):
_, x_debian_vcs_git = line.split(':', 1)
x_debian_vcs_git = x_debian_vcs_git.strip()
break
if line.startswith('Vcs-Git:'):
_, vcs_git = line.split(':', 1)
vcs_git = vcs_git.strip()
if not x_debian_vcs_git and not vcs_git:
logging.error(
"Unable to find any Vcs metadata in "
"pkg/ubuntu/devel:debian/control."
)
return 1
url = x_debian_vcs_git if x_debian_vcs_git else vcs_git
repo.add_remote_by_url(remote_name, url)
finally:
if control_file:
control_file.close()
if not no_fetch:
try:
repo.fetch_remote(remote_name, verbose=True)
except GitUbuntuRepositoryFetchError:
pass
logging.debug(
"added remote '%s' -> %s",
remote_name,
repo.raw_repo.remotes[remote_name].url,
)
return 0
def do_add(repo, package, user, url=None, remote_name=None, no_fetch=False):
"""add a remote to a repository
@repo: GitUbuntuRepository to modify
@package: source package name (XXX: is this derive-able from @repo?)
@user: remote user's repository to add as remote
@url: URL to add as a remote
@remote_name: specify the name of the new remote
@no_fetch: if True, do not fetch the remote after adding it
If url is None, the remote URL will be derived from @package and
@user.
If @remote_name is not specified, it will be set to @user.
"""
if remote_name is None:
remote_name = user
if url:
repo.add_remote_by_url(remote_name, url)
else:
repo.add_remote(
pkgname=package,
repo_owner=user,
remote_name=remote_name,
)
if not no_fetch:
try:
repo.fetch_remote(remote_name, verbose=True)
except GitUbuntuRepositoryFetchError:
pass
logging.debug(
"added remote '%s' -> %s",
remote_name,
repo.raw_repo.remotes[remote_name].url,
)
return 0
def main(
subcommand,
user,
package=None,
url=None,
lp_user=None,
directory=None,
remote_name=None,
no_fetch=False,
proto=top_level_defaults.proto,
):
"""Entry point to remote subcommand
@subcommand: string action to take. Currently only 'add' supported.
@user: string Launchpad user's repository to add
@package: string name of source package
@url: the string URL of the remote to add
@lp_user: string user to authenticate to Launchpad as
@directory: directory containing git repository to modify
@remote_name: name of remote
@no_fetch: do not fetch remote after modifying it
@proto: string protocol to use (one of 'http', 'https', 'git')
If package is None, it will be derived from HEAD's debian/changelog.
If url is None, it will be derived from @user and @package.
If lp_user is None, value of `git config gitubuntu.lpuser` will be
used.
If directory is None, the current directory is used.
If remote_name is None, the remote will be named @user.
Returns 0 if the subcommand succeeded; 1 otherwise.
"""
if directory is None:
directory = os.path.abspath(os.getcwd())
repo = GitUbuntuRepository(
local_dir=directory,
lp_user=lp_user,
fetch_proto=proto
)
try:
repo_pkg = repo.get_changelog_srcpkg_from_treeish('HEAD')
except GitUbuntuChangelogError:
repo_pkg = None
if package is not None:
if repo_pkg is not None and repo_pkg != package:
logging.warning(
"Specified sourcepackage (%s) does not match "
"debian/changelog (%s).",
package,
repo_pkg,
)
else:
if repo_pkg:
package = repo_pkg
else:
logging.error(
"Unable to determine source package name. Does "
"debian/changelog exist in the current branch?"
)
return 1
if subcommand == 'add':
if user == 'debian':
return do_add_debian(repo, package, no_fetch)
else:
return do_add(repo, package, user, url, remote_name, no_fetch)
return 1
# vi: ts=4 expandtab
|