repo = RpmGitRepository(workdir)
workdir = repo.path
except GitRepositoryError:
- pass
-
- if args.spec:
- try:
- RpmGitRepository(os.path.dirname(args.spec))
- except GitRepositoryError:
- msger.error('spec file should reside in git directory')
+ if args.spec:
+ msger.error("git project can't be found for --spec, "
+ "give it in argument or cd into it")
hostarch = get_hostarch()
if args.arch:
if args.define:
cmd += [('--define="%s"' % i) for i in args.define]
if args.spec:
- cmd += [args.spec]
+ cmd += ['--spec=%s' % args.spec]
msger.debug("running command: %s" % ' '.join(cmd))
retcode = os.system(' '.join(cmd))
changes_file_list = glob.glob("%s/%s/*.changes" % (project_root_dir,
packaging_dir))
- if changes_file_list:
+ if args.spec or not changes_file_list:
+ # Create .changes file with the same name as a spec
+ specfile = os.path.basename(utils.guess_spec(project_root_dir,
+ packaging_dir, args.spec))
+ fn_changes = os.path.splitext(specfile)[0] + ".changes"
+ fn_changes = os.path.join(project_root_dir, packaging_dir, fn_changes)
+ else:
fn_changes = changes_file_list[0]
if len(changes_file_list) > 1:
msger.warning("Found more than one changes files, %s is taken " \
% (changes_file_list[0]))
- else:
- # Create .changes file with the same name as a spec
- specfile = utils.guess_spec(project_root_dir, packaging_dir, args.spec)
- fn_changes = os.path.splitext(specfile)[0] + ".changes"
# get the commit start from the args.since
if args.since:
# Only guess spec filename here, parse later when we have the correct
# spec file at hand
- specfile = utils.guess_spec(workdir, packaging_dir, args.spec)
+ if args.commit:
+ commit = args.commit
+ elif args.include_all:
+ commit = 'WC.UNTRACKED'
+ else:
+ commit = 'HEAD'
+ relative_spec = utils.guess_spec(workdir, packaging_dir, args.spec, commit)
outdir = "%s/packaging" % workdir
if args.outdir:
export_dir = tempd.path
with utils.Workdir(workdir):
- if args.commit:
- commit = args.commit
- elif args.include_all:
- commit = 'WC.UNTRACKED'
- else:
- commit = 'HEAD'
- relative_spec = specfile.replace('%s/' % workdir, '')
export_sources(repo, commit, export_dir, relative_spec, args)
+ specfile = os.path.basename(relative_spec)
try:
- spec = rpm.parse_spec(os.path.join(export_dir,
- os.path.basename(specfile)))
+ spec = rpm.parse_spec(os.path.join(export_dir, specfile))
except GbpError, err:
msger.error('%s' % err)
# TODO: check ./packaging dir at first
packaging_dir = get_packaging_dir(args)
- specs = glob.glob('%s/%s/*.spec' % (workdir, packaging_dir))
- if not specs:
- msger.error("no spec file found under './%s'" % packaging_dir)
- specfile = utils.guess_spec(workdir, packaging_dir, args.spec)
+ if args.commit:
+ commit = args.commit
+ elif args.include_all:
+ commit = 'WC.UNTRACKED'
+ else:
+ commit = 'HEAD'
+
+ relative_spec = utils.guess_spec(workdir, packaging_dir, args.spec, commit)
+
+ if args.include_all:
+ # include_all means to use work copy,
+ # otherwise use the reversion in git history
+ spec_to_parse = os.path.join(workdir, relative_spec)
+ else:
+ content = utils.show_file_from_rev(workdir, relative_spec, commit)
+ if content is None:
+ msger.error('failed to checkout %s '
+ 'from commit: %s' % (relative_spec, commit))
+
+ tmp_spec = utils.Temp(content=content)
+ spec_to_parse = tmp_spec.path
+
# get 'name' and 'version' from spec file
try:
- spec = gbp.rpm.parse_spec(specfile)
+ spec = gbp.rpm.parse_spec(spec_to_parse)
except GbpError, err:
msger.error('%s' % err)
msger.error(str(err))
with utils.Workdir(workdir):
- if args.commit:
- commit = args.commit
- elif args.include_all:
- commit = 'WC.UNTRACKED'
- else:
- commit = 'HEAD'
- relative_spec = specfile.replace('%s/' % workdir, '')
export_sources(repo, commit, exportdir, relative_spec, args)
try:
"""Local additions to commandline parsing."""
+import os
import re
import functools
-from argparse import RawDescriptionHelpFormatter
+from argparse import RawDescriptionHelpFormatter, ArgumentTypeError
class GbsHelpFormatter(RawDescriptionHelpFormatter):
"""Changed default argparse help output by request from cmdln lovers."""
subpar.set_defaults(module="cmd_%s" % name)
return func(subpar)
return wrapper
+
+
+def basename_type(path):
+ '''validate function for base file name argument'''
+ if os.path.basename(path) != path:
+ raise ArgumentTypeError('should be a file name rather than a path')
+ return path
import shutil
import pycurl
import hashlib
+import fnmatch
import signal
+import subprocess
import xml.etree.ElementTree as ET
from collections import defaultdict
def __exit__(self, _type, _value, _tb):
os.chdir(self._cwd)
-def guess_spec(workdir, packaging_dir, default_spec):
- workdir = os.path.abspath(workdir)
- git_project = os.path.basename(workdir)
-
- if default_spec:
- default_spec = os.path.abspath(default_spec)
- if not default_spec.startswith(workdir):
- msger.error("spec file doesn't belong to the project %s: "
- "%s" % (git_project, default_spec))
- if not os.path.exists(default_spec):
- msger.error('%s does not exit' % default_spec)
- return default_spec
-
- specfile = os.path.join(workdir, packaging_dir, '%s.spec' % git_project)
- if not os.path.exists(specfile):
- specs = glob.glob(os.path.join(workdir, packaging_dir, '*.spec'))
- if not specs:
- msger.error('no spec file found under %s/%s' % (workdir,
- packaging_dir))
-
- if len(specs) > 1:
- msger.error("Can't decide which spec file to use.")
- else:
- specfile = specs[0]
- return specfile
+def guess_spec(git_path, packaging_dir, given_spec, commit_id='WC.UNTRACKED'):
+ '''guess spec file from project name if not given'''
+ git_path = os.path.abspath(git_path)
+
+ if commit_id == 'WC.UNTRACKED':
+ check = lambda fname: os.path.exists(os.path.join(git_path, fname))
+ glob_ = lambda pattern: [ name.replace(git_path+'/', '')
+ for name in glob.glob(os.path.join(git_path, pattern)) ]
+ msg = 'No such spec file %s'
+ else:
+ check = lambda fname: file_exists_in_rev(git_path, fname, commit_id)
+ glob_ = lambda pattern: glob_in_rev(git_path, pattern, commit_id)
+ msg = "No such spec file %%s in %s" % commit_id
+
+ if given_spec:
+ spec = os.path.join(packaging_dir, given_spec)
+ if not check(spec):
+ msger.error(msg % spec)
+ return spec
+
+ specs = glob_(os.path.join(packaging_dir, '*.spec'))
+ if not specs:
+ msger.error("can't find any spec file")
+
+ project_name = os.path.basename(git_path)
+ spec = os.path.join(packaging_dir, '%s.spec' % project_name)
+ return spec if spec in specs else specs[0]
+
class Temp(object):
"""
md5obj.update(data)
return md5obj.hexdigest()
+
+def show_file_from_rev(git_path, relative_path, commit_id):
+ '''return a single file content from given rev.'''
+
+ cmd = 'cd %s; git show %s:%s' % (git_path, commit_id, relative_path)
+ try:
+ return subprocess.check_output(cmd, shell=True)
+ except (subprocess.CalledProcessError, OSError), err:
+ msger.debug('failed to checkout %s from %s:%s' % (relative_path,
+ commit_id, str(err)))
+ return None
+
+
+def file_exists_in_rev(git_path, relative_path, commit_id):
+ '''return True if file exists in given rev'''
+
+ cmd = 'cd %s; git ls-tree --name-only %s %s' % (
+ git_path, commit_id, relative_path)
+
+ try:
+ output = subprocess.check_output(cmd, shell=True)
+ except (subprocess.CalledProcessError, OSError), err:
+ raise errors.GbsError('failed to check existence of %s in %s:%s' % (
+ relative_path, commit_id, str(err)))
+
+ return output != ''
+
+
+def glob_in_rev(git_path, pattern, commit_id):
+ '''glob pattern in given rev'''
+
+ path = os.path.dirname(pattern)
+ cmd = 'cd %s; git ls-tree --name-only %s %s/' % (
+ git_path, commit_id, path)
+
+ try:
+ output = subprocess.check_output(cmd, shell=True)
+ except (subprocess.CalledProcessError, OSError), err:
+ raise errors.GbsError('failed to glob %s in %s:%s' % (
+ pattern, commit_id, str(err)))
+
+ return fnmatch.filter(output.splitlines(), pattern)
import sys
import os
-from argparse import ArgumentParser, ArgumentTypeError
+from argparse import ArgumentParser
from gitbuildsys import __version__
from gitbuildsys import msger, errors
-from gitbuildsys.parsing import subparser, GbsHelpFormatter
-
-
-def abspath_arg(arg):
- '''validate path argument and convert to absolute format'''
- path = os.path.abspath(arg)
- if not os.path.exists(path):
- raise ArgumentTypeError('no such %s' % path)
- return path
+from gitbuildsys.parsing import subparser, GbsHelpFormatter, basename_type
@subparser
def export_parser(parser):
"""export files and prepare for build
Examples:
- $ gbs export --spec packaging/my.spec --commit d64065c
+ $ gbs export --spec my.spec --commit d64065c
$ gbs export --source-rpm -o /tmp/
$ gbs export --include-all
"""
help='path to git repository')
parser.add_argument('-o', '--outdir', help='output directory')
- parser.add_argument('--spec', help='specify a spec file to use')
+ parser.add_argument('--spec', type=basename_type,
+ help='specify a spec file to use. It should be a file '
+ 'name that GBS will find it in packaging dir')
parser.add_argument('-c', '--commit', help='specify a commit ID to export')
parser.add_argument('--include-all', action='store_true',
help='uncommitted changes and untracked files '
parser.add_argument('--skip-conf-repos', action="store_true",
help='skip repositories mentioned in config file')
parser.add_argument('-c', '--commit', help='specify a commit ID to build')
- parser.add_argument('--spec', type=abspath_arg,
- help='specify a spec file to use')
+ parser.add_argument('--spec', type=basename_type,
+ help='specify a spec file to use. It should be a file '
+ 'name that GBS will find it in packaging dir')
parser.add_argument('--extra-packs',
help='specify extra packages to install to build root '
'multiple packages can be separated by comma')
parser.add_argument('-P', '--profile',
help='profile to be used for building, can be given '
'without the "profile." prefix')
- parser.add_argument('--spec', help='specify a spec file to use')
+ parser.add_argument('--spec', type=basename_type,
+ help='specify a spec file to use. It should be a file '
+ 'name that GBS will find it in packaging dir')
parser.add_argument('-c', '--commit', help='specify a commit ID to build')
parser.add_argument('--buildlog', action='store_true',
help='get buildlog from build sever')
default=os.getcwd(),
help='path to git repository')
- parser.add_argument('--spec', help='specify a spec file to use')
+ parser.add_argument('--spec', type=basename_type,
+ help='specify a spec file to use. It should be a file '
+ 'name that GBS will find it in packaging dir')
parser.add_argument('-s', '--since',
help='commit to start from')
parser.add_argument('-m', '--message',