buildpackage_rpm.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. # vim: set fileencoding=utf-8 :
  2. #
  3. # (C) 2006-2011,2015 Guido Guenther <agx@sigxcpu.org>
  4. # (C) 2012-2015 Intel Corporation <markus.lehtonen@linux.intel.com>
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, please see
  17. # <http://www.gnu.org/licenses/>
  18. #
  19. """Build an RPM package out of a Git repository"""
  20. from six.moves import configparser
  21. import os
  22. import shutil
  23. import sys
  24. import gbp.log
  25. import gbp.notifications
  26. import gbp.rpm as rpm
  27. from gbp.command_wrappers import Command, RunAtCommand, CommandExecFailed
  28. from gbp.config import GbpOptionParserRpm, GbpOptionGroup
  29. from gbp.errors import GbpError
  30. from gbp.format import format_str
  31. from gbp.pkg import compressor_opts
  32. from gbp.rpm.git import GitRepositoryError, RpmGitRepository
  33. from gbp.rpm.policy import RpmPkgPolicy
  34. from gbp.tmpfile import init_tmpdir, del_tmpdir, tempfile
  35. from gbp.scripts.common.buildpackage import (index_name, wc_name,
  36. git_archive_submodules,
  37. git_archive_single, dump_tree,
  38. write_wc, drop_index)
  39. from gbp.scripts.pq_rpm import parse_spec
  40. class GbpAutoGenerateError(GbpError):
  41. pass
  42. def makedir(path):
  43. """Create directory"""
  44. try:
  45. if not os.path.exists(path):
  46. os.makedirs(path)
  47. except OSError as err:
  48. raise GbpError("Cannot create dir %s: %s" % (path, err))
  49. return path
  50. def git_archive(repo, spec, output_dir, treeish, prefix, comp_level,
  51. with_submodules):
  52. "Create a compressed orig tarball in output_dir using git_archive"
  53. comp_opts = ''
  54. if spec.orig_src['compression']:
  55. comp_opts = compressor_opts[spec.orig_src['compression']][0]
  56. output = os.path.join(output_dir, spec.orig_src['filename'])
  57. # Remove extra slashes from prefix, will be added by git_archive_x funcs
  58. prefix = prefix.strip('/')
  59. try:
  60. if repo.has_submodules(treeish) and with_submodules:
  61. repo.update_submodules()
  62. git_archive_submodules(repo, treeish, output, prefix,
  63. spec.orig_src['compression'],
  64. comp_level, comp_opts,
  65. spec.orig_src['archive_fmt'])
  66. else:
  67. git_archive_single(treeish, output, prefix,
  68. spec.orig_src['compression'], comp_level,
  69. comp_opts, spec.orig_src['archive_fmt'])
  70. except (GitRepositoryError, CommandExecFailed):
  71. gbp.log.err("Error generating submodules' archives")
  72. return False
  73. return True
  74. def prepare_upstream_tarball(repo, spec, options, output_dir):
  75. """Make sure we have an upstream tarball"""
  76. # look in tarball_dir first, if found force a symlink to it
  77. orig_file = spec.orig_src['filename']
  78. if options.tarball_dir:
  79. gbp.log.debug("Looking for orig tarball '%s' at '%s'" %
  80. (orig_file, options.tarball_dir))
  81. if not RpmPkgPolicy.symlink_orig(orig_file, options.tarball_dir,
  82. output_dir, force=True):
  83. gbp.log.info("Orig tarball '%s' not found at '%s'" %
  84. (orig_file, options.tarball_dir))
  85. else:
  86. gbp.log.info("Orig tarball '%s' found at '%s'" %
  87. (orig_file, options.tarball_dir))
  88. # build an orig unless the user forbids it, always build (and overwrite
  89. # pre-existing) if user forces it
  90. if options.force_create or (not options.no_create_orig and not
  91. RpmPkgPolicy.has_orig(orig_file, output_dir)):
  92. if not pristine_tar_build_orig(repo, orig_file, output_dir, options):
  93. upstream_tree = git_archive_build_orig(repo, spec, output_dir,
  94. options)
  95. if options.pristine_tar_commit:
  96. if repo.pristine_tar.has_commit(orig_file):
  97. gbp.log.debug("%s already on pristine tar branch" %
  98. orig_file)
  99. else:
  100. archive = os.path.join(output_dir, orig_file)
  101. gbp.log.debug("Adding %s to pristine-tar branch" %
  102. archive)
  103. repo.pristine_tar.commit(archive, upstream_tree)
  104. def pristine_tar_build_orig(repo, orig_file, output_dir, options):
  105. """Build orig using pristine-tar"""
  106. if options.pristine_tar:
  107. if not repo.has_branch(repo.pristine_tar_branch):
  108. gbp.log.warn('Pristine-tar branch "%s" not found' %
  109. repo.pristine_tar.branch)
  110. try:
  111. repo.pristine_tar.checkout(os.path.join(output_dir, orig_file))
  112. return True
  113. except CommandExecFailed:
  114. if options.pristine_tar_commit:
  115. gbp.log.debug("pristine-tar checkout failed, "
  116. "will commit tarball due to "
  117. "'--pristine-tar-commit'")
  118. elif not options.force_create:
  119. raise
  120. return False
  121. def get_upstream_tree(repo, version, options):
  122. """Determine the upstream tree from the given options"""
  123. if options.upstream_tree.upper() == 'TAG':
  124. tag_str_fields = {'upstreamversion': version,
  125. 'version': version}
  126. upstream_tree = repo.version_to_tag(options.upstream_tag,
  127. tag_str_fields)
  128. elif options.upstream_tree.upper() == 'BRANCH':
  129. if not repo.has_branch(options.upstream_branch):
  130. raise GbpError("%s is not a valid branch" % options.upstream_branch)
  131. upstream_tree = options.upstream_branch
  132. else:
  133. upstream_tree = get_tree(repo, options.upstream_tree)
  134. if not repo.has_treeish(upstream_tree):
  135. raise GbpError('Invalid upstream treeish %s' % upstream_tree)
  136. return upstream_tree
  137. def get_tree(repo, tree_name):
  138. """
  139. Get/create a tree-ish to be used for exporting and diffing. Accepts
  140. special keywords for git index and working copies.
  141. """
  142. try:
  143. if tree_name == index_name:
  144. # Write a tree of the index
  145. tree = repo.write_tree()
  146. elif tree_name == wc_name:
  147. # Write a tree of the working copy
  148. tree = write_wc(repo)
  149. else:
  150. tree = tree_name
  151. except GitRepositoryError as err:
  152. raise GbpError(err)
  153. if not repo.has_treeish(tree):
  154. raise GbpError('Invalid treeish object %s' % tree)
  155. return tree
  156. def get_current_branch(repo):
  157. """Get the currently checked-out branch"""
  158. try:
  159. branch = repo.get_branch()
  160. except GitRepositoryError:
  161. branch = None
  162. return branch
  163. def get_vcs_info(repo, treeish):
  164. """Get the info for spec vcs tag"""
  165. info = {}
  166. try:
  167. info['tagname'] = repo.describe(treeish, longfmt=True, always=True,
  168. abbrev=40)
  169. info['commit'] = repo.rev_parse('%s^0' % treeish)
  170. info['commitish'] = repo.rev_parse('%s' % treeish)
  171. except GitRepositoryError:
  172. # If tree is not commit-ish, expect it to be from current HEAD
  173. info['tagname'] = repo.describe('HEAD', longfmt=True, always=True,
  174. abbrev=40) + '-dirty'
  175. info['commit'] = repo.rev_parse('HEAD') + '-dirty'
  176. info['commitish'] = info['commit']
  177. return info
  178. def git_archive_build_orig(repo, spec, output_dir, options):
  179. """
  180. Build orig tarball using git-archive
  181. @param repo: our git repository
  182. @type repo: L{RpmGitRepository}
  183. @param spec: spec file of the package
  184. @type spec: L{SpecFile}
  185. @param output_dir: where to put the tarball
  186. @type output_dir: C{Str}
  187. @param options: the parsed options
  188. @type options: C{dict} of options
  189. @return: the tree we built the tarball from
  190. @rtype: C{str}
  191. """
  192. try:
  193. orig_prefix = spec.orig_src['prefix']
  194. upstream_tree = get_upstream_tree(repo, spec.upstreamversion, options)
  195. gbp.log.info("%s does not exist, creating from '%s'" %
  196. (spec.orig_src['filename'], upstream_tree))
  197. if spec.orig_src['compression']:
  198. gbp.log.debug("Building upstream source archive with compression "
  199. "'%s -%s'" % (spec.orig_src['compression'],
  200. options.comp_level))
  201. if not git_archive(repo, spec, output_dir, upstream_tree,
  202. orig_prefix, options.comp_level,
  203. options.with_submodules):
  204. raise GbpError("Cannot create upstream tarball at '%s'" %
  205. output_dir)
  206. except (GitRepositoryError, GbpError) as err:
  207. raise GbpAutoGenerateError(str(err))
  208. return upstream_tree
  209. def is_native(repo, options):
  210. """Determine whether a package is native or non-native"""
  211. if options.native.is_auto():
  212. if repo.has_branch(options.upstream_branch):
  213. return False
  214. # Check remotes, too
  215. for remote_branch in repo.get_remote_branches():
  216. remote, branch = remote_branch.split('/', 1)
  217. if branch == options.upstream_branch:
  218. gbp.log.debug("Found upstream branch '%s' from remote '%s'" %
  219. (remote, branch))
  220. return False
  221. return True
  222. return options.native.is_on()
  223. def setup_builder(options, builder_args):
  224. """Setup args and options for builder script"""
  225. if options.builder == 'rpmbuild':
  226. if len(builder_args) == 0:
  227. builder_args.append('-ba')
  228. builder_args.extend([
  229. '--define "_topdir %s"' % os.path.abspath(options.export_dir),
  230. '--define "_specdir %%_topdir/%s"' % options.export_specdir,
  231. '--define "_sourcedir %%_topdir/%s"' % options.export_sourcedir])
  232. def packaging_tag_data(repo, commit, name, version, options):
  233. """Compose packaging tag name and msg"""
  234. version_dict = dict(version, version=rpm.compose_version_str(version))
  235. # Compose tag name and message
  236. tag_name_fields = dict(version_dict, vendor=options.vendor.lower())
  237. tag_name = repo.version_to_tag(options.packaging_tag, tag_name_fields)
  238. tag_msg = format_str(options.packaging_tag_msg,
  239. dict(version_dict, pkg=name,
  240. vendor=options.vendor))
  241. return (tag_name, tag_msg)
  242. def setup_mock(options):
  243. """setup everything to use gbp-builder-mock"""
  244. if options.use_mock:
  245. options.builder = '/usr/share/git-buildpackage/gbp-builder-mock'
  246. options.cleaner = '/bin/true'
  247. os.environ['GBP_BUILDER_MOCK_DIST'] = options.mock_dist
  248. if options.mock_arch:
  249. os.environ['GBP_BUILDER_MOCK_ARCH'] = options.mock_arch
  250. if options.mock_root:
  251. os.environ['GBP_BUILDER_MOCK_ROOT'] = options.mock_root
  252. os.environ['GBP_BUILDER_MOCK_EXPORT_DIR'] = options.export_dir
  253. if options.mock_options:
  254. os.environ['GBP_BUILDER_MOCK_OPTIONS'] = options.mock_options
  255. def create_packaging_tag(repo, commit, name, version, options):
  256. """Create a packaging/release Git tag"""
  257. tag_name, tag_msg = packaging_tag_data(repo, commit, name, version, options)
  258. if options.retag and repo.has_tag(tag_name):
  259. repo.delete_tag(tag_name)
  260. repo.create_tag(name=tag_name, msg=tag_msg, sign=options.sign_tags,
  261. keyid=options.keyid, commit=commit)
  262. return tag_name
  263. def disable_hooks(options):
  264. """Disable all hooks (except for builder)"""
  265. for hook in ['cleaner', 'postexport', 'prebuild', 'postbuild', 'posttag']:
  266. if getattr(options, hook):
  267. gbp.log.info("Disabling '%s' hook" % hook)
  268. setattr(options, hook, '')
  269. def build_parser(name, prefix=None, git_treeish=None):
  270. """Construct config/option parser"""
  271. try:
  272. parser = GbpOptionParserRpm(command=os.path.basename(name),
  273. prefix=prefix)
  274. except configparser.ParsingError as err:
  275. gbp.log.err(err)
  276. return None
  277. tag_group = GbpOptionGroup(parser, "tag options",
  278. "options related to git tag creation")
  279. branch_group = GbpOptionGroup(parser, "branch options",
  280. "branch layout options")
  281. cmd_group = GbpOptionGroup(parser, "external command options",
  282. "how and when to invoke external commands and hooks")
  283. orig_group = GbpOptionGroup(parser, "orig tarball options",
  284. "options related to the creation of the orig tarball")
  285. export_group = GbpOptionGroup(parser, "export build-tree options",
  286. "alternative build tree related options")
  287. parser.add_option_group(tag_group)
  288. parser.add_option_group(orig_group)
  289. parser.add_option_group(branch_group)
  290. parser.add_option_group(cmd_group)
  291. parser.add_option_group(export_group)
  292. parser.add_boolean_config_file_option(option_name="ignore-new",
  293. dest="ignore_new")
  294. parser.add_option("--git-verbose", action="store_true", dest="verbose",
  295. default=False, help="verbose command execution")
  296. parser.add_config_file_option(option_name="tmp-dir", dest="tmp_dir")
  297. parser.add_config_file_option(option_name="color", dest="color",
  298. type='tristate')
  299. parser.add_config_file_option(option_name="color-scheme",
  300. dest="color_scheme")
  301. parser.add_config_file_option(option_name="notify", dest="notify",
  302. type='tristate')
  303. parser.add_config_file_option(option_name="vendor", action="store",
  304. dest="vendor")
  305. parser.add_config_file_option(option_name="native", dest="native",
  306. type='tristate')
  307. tag_group.add_option("--git-tag", action="store_true", dest="tag",
  308. default=False,
  309. help="create a tag after a successful build")
  310. tag_group.add_option("--git-tag-only", action="store_true", dest="tag_only",
  311. default=False,
  312. help="don't build, only tag and run the posttag hook")
  313. tag_group.add_option("--git-retag", action="store_true", dest="retag",
  314. default=False, help="don't fail if the tag already exists")
  315. tag_group.add_boolean_config_file_option(option_name="sign-tags",
  316. dest="sign_tags")
  317. tag_group.add_config_file_option(option_name="keyid", dest="keyid")
  318. tag_group.add_config_file_option(option_name="packaging-tag",
  319. dest="packaging_tag")
  320. tag_group.add_config_file_option(option_name="packaging-tag-msg",
  321. dest="packaging_tag_msg")
  322. tag_group.add_config_file_option(option_name="upstream-tag",
  323. dest="upstream_tag")
  324. orig_group.add_config_file_option(option_name="upstream-tree",
  325. dest="upstream_tree")
  326. orig_group.add_boolean_config_file_option(option_name="pristine-tar",
  327. dest="pristine_tar")
  328. orig_group.add_boolean_config_file_option(option_name="pristine-tar-commit",
  329. dest="pristine_tar_commit")
  330. orig_group.add_config_file_option(option_name="force-create",
  331. dest="force_create", action="store_true",
  332. help="force creation of upstream source tarball")
  333. orig_group.add_config_file_option(option_name="no-create-orig",
  334. dest="no_create_orig", action="store_true",
  335. help="don't create upstream source tarball")
  336. orig_group.add_config_file_option(option_name="tarball-dir",
  337. dest="tarball_dir", type="path",
  338. help="location to look for external tarballs")
  339. orig_group.add_config_file_option(option_name="compression-level",
  340. dest="comp_level",
  341. help="Compression level, default is "
  342. "'%(compression-level)s'")
  343. branch_group.add_config_file_option(option_name="upstream-branch",
  344. dest="upstream_branch")
  345. branch_group.add_config_file_option(option_name="packaging-branch",
  346. dest="packaging_branch")
  347. branch_group.add_boolean_config_file_option(option_name = "ignore-branch",
  348. dest="ignore_branch")
  349. branch_group.add_boolean_config_file_option(option_name = "submodules",
  350. dest="with_submodules")
  351. cmd_group.add_config_file_option(option_name="builder", dest="builder",
  352. help="command to build the package, default is "
  353. "'%(builder)s'")
  354. cmd_group.add_config_file_option(option_name="cleaner", dest="cleaner",
  355. help="command to clean the working copy, default is "
  356. "'%(cleaner)s'")
  357. cmd_group.add_config_file_option(option_name="prebuild", dest="prebuild",
  358. help="command to run before a build, default is "
  359. "'%(prebuild)s'")
  360. cmd_group.add_config_file_option(option_name="postexport",
  361. dest="postexport",
  362. help="command to run after exporting the source tree, "
  363. "default is '%(postexport)s'")
  364. cmd_group.add_config_file_option(option_name="postbuild", dest="postbuild",
  365. help="hook run after a successful build, default is "
  366. "'%(postbuild)s'")
  367. cmd_group.add_config_file_option(option_name="posttag", dest="posttag",
  368. help="hook run after a successful tag operation, default "
  369. "is '%(posttag)s'")
  370. cmd_group.add_boolean_config_file_option(option_name="mock", dest="use_mock")
  371. cmd_group.add_config_file_option(option_name="dist", dest="mock_dist")
  372. cmd_group.add_config_file_option(option_name="arch", dest="mock_arch")
  373. cmd_group.add_config_file_option(option_name="mock-root", dest="mock_root")
  374. cmd_group.add_config_file_option(option_name="mock-options", dest="mock_options")
  375. cmd_group.add_boolean_config_file_option(option_name="hooks", dest="hooks")
  376. export_group.add_option("--git-no-build", action="store_true",
  377. dest="no_build",
  378. help="Don't run builder or the associated hooks")
  379. export_group.add_config_file_option(option_name="export-dir",
  380. dest="export_dir", type="path",
  381. help="Build topdir, also export the sources under "
  382. "EXPORT_DIR, default is '%(export-dir)s'")
  383. export_group.add_config_file_option(option_name="export-specdir",
  384. dest="export_specdir", type="path")
  385. export_group.add_config_file_option(option_name="export-sourcedir",
  386. dest="export_sourcedir", type="path")
  387. export_group.add_config_file_option("export", dest="export",
  388. metavar="TREEISH",
  389. help="export treeish object TREEISH, default is "
  390. "'%(export)s'")
  391. export_group.add_config_file_option(option_name="packaging-dir",
  392. dest="packaging_dir")
  393. export_group.add_config_file_option(option_name="spec-file",
  394. dest="spec_file")
  395. return parser
  396. def parse_args(argv, prefix, git_treeish=None):
  397. """Parse config and command line arguments"""
  398. args = [arg for arg in argv[1:] if arg.find('--%s' % prefix) == 0]
  399. builder_args = [arg for arg in argv[1:] if arg.find('--%s' % prefix) == -1]
  400. # We handle these although they don't have a --git- prefix
  401. for arg in ["--help", "-h", "--version"]:
  402. if arg in builder_args:
  403. args.append(arg)
  404. parser = build_parser(argv[0], prefix=prefix, git_treeish=git_treeish)
  405. if not parser:
  406. return None, None, None
  407. options, args = parser.parse_args(args)
  408. gbp.log.setup(options.color, options.verbose, options.color_scheme)
  409. if not options.hooks:
  410. disable_hooks(options)
  411. if options.retag:
  412. if not options.tag and not options.tag_only:
  413. gbp.log.err("'--%sretag' needs either '--%stag' or '--%stag-only'" %
  414. (prefix, prefix, prefix))
  415. return None, None, None
  416. return options, args, builder_args
  417. def main(argv):
  418. """Entry point for gbp-buildpackage-rpm"""
  419. retval = 0
  420. prefix = "git-"
  421. spec = None
  422. options, gbp_args, builder_args = parse_args(argv, prefix)
  423. if not options:
  424. return 1
  425. try:
  426. repo = RpmGitRepository(os.path.curdir)
  427. except GitRepositoryError:
  428. gbp.log.err("%s is not a git repository" % (os.path.abspath('.')))
  429. return 1
  430. # Determine tree-ish to be exported
  431. try:
  432. tree = get_tree(repo, options.export)
  433. except GbpError as err:
  434. gbp.log.err('Failed to determine export treeish: %s' % err)
  435. return 1
  436. # Re-parse config options with using the per-tree config file(s) from the
  437. # exported tree-ish
  438. options, gbp_args, builder_args = parse_args(argv, prefix, tree)
  439. branch = get_current_branch(repo)
  440. try:
  441. init_tmpdir(options.tmp_dir, prefix='buildpackage-rpm_')
  442. tree = get_tree(repo, options.export)
  443. spec = parse_spec(options, repo, treeish=tree)
  444. Command(options.cleaner, shell=True)()
  445. if not options.ignore_new:
  446. ret, out = repo.is_clean()
  447. if not ret:
  448. gbp.log.err("You have uncommitted changes in your source tree:")
  449. gbp.log.err(out)
  450. raise GbpError("Use --git-ignore-new to ignore.")
  451. if not options.ignore_new and not options.ignore_branch:
  452. if branch != options.packaging_branch:
  453. gbp.log.err("You are not on branch '%s' but on '%s'" %
  454. (options.packaging_branch, branch))
  455. raise GbpError("Use --git-ignore-branch to ignore or "
  456. "--git-packaging-branch to set the branch name.")
  457. # Dump from git to a temporary directory:
  458. packaging_tree = '%s:%s' % (tree, options.packaging_dir)
  459. dump_dir = tempfile.mkdtemp(prefix='packaging_')
  460. gbp.log.debug("Dumping packaging files to '%s'" % dump_dir)
  461. if not dump_tree(repo, dump_dir, packaging_tree, False, False):
  462. raise GbpError
  463. # Re-parse spec from dump dir to get version etc.
  464. spec = rpm.SpecFile(os.path.join(dump_dir, spec.specfile))
  465. if not options.tag_only:
  466. # Setup builder opts
  467. setup_builder(options, builder_args)
  468. if options.use_mock:
  469. setup_mock(options)
  470. # Prepare final export dirs
  471. export_dir = makedir(options.export_dir)
  472. source_dir = makedir(os.path.join(export_dir,
  473. options.export_sourcedir))
  474. spec_dir = makedir(os.path.join(export_dir, options.export_specdir))
  475. # Move packaging files to final export dir
  476. gbp.log.debug("Exporting packaging files from '%s' to '%s'" %
  477. (dump_dir, export_dir))
  478. for fname in os.listdir(dump_dir):
  479. src = os.path.join(dump_dir, fname)
  480. if fname == spec.specfile:
  481. dst = os.path.join(spec_dir, fname)
  482. else:
  483. dst = os.path.join(source_dir, fname)
  484. try:
  485. shutil.copy2(src, dst)
  486. except IOError as err:
  487. raise GbpError("Error exporting packaging files: %s" % err)
  488. spec.specdir = os.path.abspath(spec_dir)
  489. # Get/build the orig tarball
  490. if is_native(repo, options):
  491. if spec.orig_src and not options.no_create_orig:
  492. # Just build source archive from the exported tree
  493. gbp.log.info("Creating (native) source archive %s from '%s'"
  494. % (spec.orig_src['filename'], tree))
  495. if spec.orig_src['compression']:
  496. gbp.log.debug("Building source archive with "
  497. "compression '%s -%s'" %
  498. (spec.orig_src['compression'],
  499. options.comp_level))
  500. orig_prefix = spec.orig_src['prefix']
  501. if not git_archive(repo, spec, source_dir, tree,
  502. orig_prefix, options.comp_level,
  503. options.with_submodules):
  504. raise GbpError("Cannot create source tarball at '%s'" %
  505. source_dir)
  506. # Non-native packages: create orig tarball from upstream
  507. elif spec.orig_src:
  508. prepare_upstream_tarball(repo, spec, options, source_dir)
  509. # Run postexport hook
  510. if options.postexport:
  511. RunAtCommand(options.postexport, shell=True,
  512. extra_env={'GBP_GIT_DIR': repo.git_dir,
  513. 'GBP_TMP_DIR': export_dir}
  514. )(dir=export_dir)
  515. # Do actual build
  516. if not options.no_build and not options.tag_only:
  517. if options.prebuild:
  518. RunAtCommand(options.prebuild, shell=True,
  519. extra_env={'GBP_GIT_DIR': repo.git_dir,
  520. 'GBP_BUILD_DIR': export_dir}
  521. )(dir=export_dir)
  522. # Finally build the package:
  523. if options.builder.startswith("rpmbuild"):
  524. builder_args.append(os.path.join(spec.specdir,
  525. spec.specfile))
  526. else:
  527. builder_args.append(spec.specfile)
  528. RunAtCommand(options.builder, builder_args, shell=True,
  529. extra_env={'GBP_BUILD_DIR': export_dir}
  530. )(dir=export_dir)
  531. if options.postbuild:
  532. changes = os.path.abspath("%s/%s.changes" % (source_dir,
  533. spec.name))
  534. gbp.log.debug("Looking for changes file %s" % changes)
  535. Command(options.postbuild, shell=True,
  536. extra_env={'GBP_CHANGES_FILE': changes,
  537. 'GBP_BUILD_DIR': export_dir})()
  538. # Tag (note: tags the exported version)
  539. if options.tag or options.tag_only:
  540. gbp.log.info("Tagging %s" % rpm.compose_version_str(spec.version))
  541. tag = create_packaging_tag(repo, tree, spec.name, spec.version,
  542. options)
  543. vcs_info = get_vcs_info(repo, tag)
  544. if options.posttag:
  545. sha = repo.rev_parse("%s^{}" % tag)
  546. Command(options.posttag, shell=True,
  547. extra_env={'GBP_TAG': tag,
  548. 'GBP_BRANCH': branch,
  549. 'GBP_SHA1': sha})()
  550. else:
  551. vcs_info = get_vcs_info(repo, tree)
  552. except CommandExecFailed:
  553. retval = 1
  554. except GitRepositoryError as err:
  555. gbp.log.err("Git command failed: %s" % err)
  556. retval = 1
  557. except GbpAutoGenerateError as err:
  558. if len(err.__str__()):
  559. gbp.log.err(err)
  560. retval = 2
  561. except GbpError as err:
  562. if len(err.__str__()):
  563. gbp.log.err(err)
  564. retval = 1
  565. finally:
  566. drop_index()
  567. del_tmpdir()
  568. if not options.tag_only:
  569. if spec and options.notify:
  570. summary = "Gbp-rpm %s" % ["failed", "successful"][not retval]
  571. message = ("Build of %s %s %s" % (spec.name,
  572. rpm.compose_version_str(spec.version),
  573. ["failed", "succeeded"][not retval]))
  574. if not gbp.notifications.notify(summary, message, options.notify):
  575. gbp.log.err("Failed to send notification")
  576. retval = 1
  577. return retval
  578. if __name__ == '__main__':
  579. sys.exit(main(sys.argv))