1 # vim: set fileencoding=utf-8 :
3 # (C) 2006, 2007, 2009, 2011 Guido Guenther <agx@sigxcpu.org>
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 """Import a new upstream version into a GIT repository"""
23 import gbp.tmpfile as tempfile
24 import gbp.command_wrappers as gbpc
25 from gbp.deb import (DebianPkgPolicy, parse_changelog_repo)
26 from gbp.deb.upstreamsource import DebianUpstreamSource
27 from gbp.deb.uscan import (Uscan, UscanError)
28 from gbp.deb.changelog import ChangeLog, NoChangeLogError
29 from gbp.deb.git import (GitRepositoryError, DebianGitRepository)
30 from gbp.config import GbpOptionParserDebian, GbpOptionGroup, no_upstream_branch_msg
31 from gbp.errors import GbpError
32 from gbp.format import format_msg
34 from gbp.pkg import compressor_opts
35 from gbp.scripts.common.import_orig import (cleanup_tmp_tree, ask_package_name,
40 def upstream_import_commit_msg(options, version):
41 return options.import_msg % dict(version=version)
44 def detect_name_and_version(repo, source, options):
45 # Guess defaults for the package name and version from the
47 guessed_package, guessed_version = source.guess_version()
49 # Try to find the source package name
51 cp = ChangeLog(filename='debian/changelog')
52 sourcepackage = cp['Source']
53 except NoChangeLogError:
55 # Check the changelog file from the repository, in case
56 # we're not on the debian-branch (but upstream, for
58 cp = parse_changelog_repo(repo, options.packaging_branch, 'debian/changelog')
59 sourcepackage = cp['Source']
60 except NoChangeLogError:
61 if options.interactive:
62 sourcepackage = ask_package_name(guessed_package,
63 DebianPkgPolicy.is_valid_packagename,
64 DebianPkgPolicy.packagename_msg)
67 sourcepackage = guessed_package
69 raise GbpError("Couldn't determine upstream package name. Use --interactive.")
71 # Try to find the version.
73 version = options.version
75 if options.interactive:
76 version = ask_package_version(guessed_version,
77 DebianPkgPolicy.is_valid_upstreamversion,
78 DebianPkgPolicy.upstreamversion_msg)
81 version = guessed_version
83 raise GbpError("Couldn't determine upstream version. Use '-u<version>' or --interactive.")
85 return (sourcepackage, version)
88 def find_source(use_uscan, args):
89 """Find the tarball to import - either via uscan or via command line argument
90 @return: upstream source filename or None if nothing to import
92 @raise GbpError: raised on all detected errors
96 raise GbpError("you can't pass both --uscan and a filename.")
99 gbp.log.info("Launching uscan...")
102 except UscanError as e:
103 raise GbpError("%s" % e)
105 if not uscan.uptodate:
107 gbp.log.info("using %s" % uscan.tarball)
108 args.append(uscan.tarball)
110 raise GbpError("uscan didn't download anything, and no source was found in ../")
112 gbp.log.info("package is up to date, nothing to do.")
114 if len(args) > 1: # source specified
115 raise GbpError("More than one archive specified. Try --help.")
117 raise GbpError("No archive to import specified. Try --help.")
119 archive = DebianUpstreamSource(args[0])
123 def pristine_tarball_name(source, pkg_name, pkg_version):
124 if source.is_tarball():
125 if source.compression:
126 comp_ext = '.' + compressor_opts[source.compression][1]
130 # Need to repack and/or mangle filename if the archive is not
131 # pristine-tar-compatible -> we decide to create gz compressed tarball
133 return '%s_%s.orig.tar%s' % (pkg_name, pkg_version, comp_ext)
136 def set_bare_repo_options(options):
137 """Modify options for import into a bare repository"""
138 if options.pristine_tar or options.merge:
139 gbp.log.info("Bare repository: setting %s%s options"
140 % (["", " '--no-pristine-tar'"][options.pristine_tar],
141 ["", " '--no-merge'"][options.merge]))
142 options.pristine_tar = False
143 options.merge = False
146 def build_parser(name):
148 parser = GbpOptionParserDebian(command=os.path.basename(name), prefix='',
149 usage='%prog [options] /path/to/upstream-version.tar.gz | --uscan')
150 except ConfigParser.ParsingError as err:
154 import_group = GbpOptionGroup(parser, "import options",
155 "pristine-tar and filtering")
156 tag_group = GbpOptionGroup(parser, "tag options",
157 "options related to git tag creation")
158 branch_group = GbpOptionGroup(parser, "version and branch naming options",
159 "version number and branch layout options")
160 cmd_group = GbpOptionGroup(parser, "external command options", "how and when to invoke external commands and hooks")
162 for group in [import_group, branch_group, tag_group, cmd_group ]:
163 parser.add_option_group(group)
165 branch_group.add_option("-u", "--upstream-version", dest="version",
166 help="Upstream Version")
167 branch_group.add_config_file_option(option_name="debian-branch",
168 dest="packaging_branch")
169 branch_group.add_config_file_option(option_name="upstream-branch",
170 dest="upstream_branch")
171 branch_group.add_option("--upstream-vcs-tag", dest="vcs_tag",
172 help="Upstream VCS tag add to the merge commit")
173 branch_group.add_boolean_config_file_option(option_name="merge", dest="merge")
174 branch_group.add_boolean_config_file_option(
175 option_name="create-missing-branches",
176 dest="create_missing_branches")
178 tag_group.add_boolean_config_file_option(option_name="sign-tags",
180 tag_group.add_config_file_option(option_name="keyid",
182 tag_group.add_config_file_option(option_name="upstream-tag",
184 import_group.add_config_file_option(option_name="filter",
185 dest="filters", action="append")
186 import_group.add_boolean_config_file_option(option_name="pristine-tar",
188 import_group.add_boolean_config_file_option(option_name="filter-pristine-tar",
189 dest="filter_pristine_tar")
190 import_group.add_config_file_option(option_name="import-msg",
192 import_group.add_boolean_config_file_option(option_name="symlink-orig",
194 cmd_group.add_config_file_option(option_name="postimport", dest="postimport")
196 parser.add_boolean_config_file_option(option_name="interactive",
198 parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
199 help="verbose command execution")
200 parser.add_config_file_option(option_name="color", dest="color", type='tristate')
201 parser.add_config_file_option(option_name="color-scheme",
203 parser.add_config_file_option(option_name="tmp-dir", dest="tmp_dir")
205 # Accepted for compatibility
206 parser.add_option("--no-dch", dest='no_dch', action="store_true",
207 default=False, help="deprecated - don't use.")
208 parser.add_option("--uscan", dest='uscan', action="store_true",
209 default=False, help="use uscan(1) to download the new tarball.")
213 def parse_args(argv):
214 parser = build_parser(argv[0])
218 (options, args) = parser.parse_args(argv[1:])
219 gbp.log.setup(options.color, options.verbose, options.color_scheme)
222 gbp.log.warn("'--no-dch' passed. This is now the default, please remove this option.")
230 (options, args) = parse_args(argv)
234 tmpdir = tempfile.mkdtemp(dir=options.tmp_dir, prefix='import-orig_')
237 source = find_source(options.uscan, args)
242 repo = DebianGitRepository('.')
243 except GitRepositoryError:
244 raise GbpError("%s is not a git repository" % (os.path.abspath('.')))
246 # an empty repo has now branches:
247 initial_branch = repo.get_branch()
248 is_empty = False if initial_branch else True
250 if not repo.has_branch(options.upstream_branch) and not is_empty:
251 if options.create_missing_branches:
252 gbp.log.info("Will create missing branch '%s'" %
253 options.upstream_branch)
255 raise GbpError(no_upstream_branch_msg % options.upstream_branch)
257 (pkg_name, version) = detect_name_and_version(repo, source, options)
259 (clean, out) = repo.is_clean()
260 if not clean and not is_empty:
261 gbp.log.err("Repository has uncommitted changes, commit these first: ")
265 set_bare_repo_options(options)
267 # Prepare sources for importing
268 pristine_name = pristine_tarball_name(source, pkg_name, version)
269 prepare_pristine = pristine_name if options.pristine_tar else None
270 unpacked_orig, pristine_orig = prepare_sources(
271 source, pkg_name, version, prepare_pristine, options.filters,
272 options.filter_pristine_tar, None, tmpdir)
274 # Don't mess up our repo with git metadata from an upstream tarball
276 if os.path.isdir(os.path.join(unpacked_orig, '.git/')):
277 raise GbpError("The orig tarball contains .git metadata - giving up.")
282 upstream_branch = [ options.upstream_branch, 'master' ][is_empty]
283 filter_msg = ["", " (filtering out %s)"
284 % options.filters][len(options.filters) > 0]
285 gbp.log.info("Importing '%s' to branch '%s'%s..." % (source.path,
288 gbp.log.info("Source package is %s" % pkg_name)
289 gbp.log.info("Upstream version is %s" % version)
291 import_branch = [ options.upstream_branch, None ][is_empty]
292 msg = upstream_import_commit_msg(options, version)
295 parents = [repo.rev_parse("%s^{}" % options.vcs_tag)]
299 commit = repo.commit_dir(unpacked_orig,
301 branch=import_branch,
302 other_parents=parents,
303 create_missing_branch=options.create_missing_branches)
305 if options.pristine_tar and pristine_orig:
306 repo.pristine_tar.commit(pristine_orig, upstream_branch)
308 tag = repo.version_to_tag(options.upstream_tag, version)
309 repo.create_tag(name=tag,
310 msg="Upstream version %s" % version,
312 sign=options.sign_tags,
315 repo.create_branch(options.upstream_branch, rev=commit)
316 repo.force_head(options.upstream_branch, hard=True)
318 gbp.log.info("Merging to '%s'" % options.packaging_branch)
319 repo.set_branch(options.packaging_branch)
322 except GitRepositoryError:
323 raise GbpError("Merge failed, please resolve.")
324 if options.postimport:
326 if os.access('debian/changelog', os.R_OK):
327 # No need to check the changelog file from the
328 # repository, since we're certain that we're on
330 cp = ChangeLog(filename='debian/changelog')
332 epoch = '%s:' % cp.epoch
333 info = { 'version': "%s%s-1" % (epoch, version) }
334 env = { 'GBP_BRANCH': options.packaging_branch }
335 gbpc.Command(format_msg(options.postimport, info), extra_env=env, shell=True)()
336 # Update working copy and index if we've possibly updated the
338 current_branch = repo.get_branch()
339 if current_branch in [ options.upstream_branch,
340 repo.pristine_tar_branch]:
341 repo.force_head(current_branch, hard=True)
342 # Create symlink, if requested
343 if options.symlink_orig:
344 if source.is_tarball():
345 link = os.path.join('..', pristine_name)
346 if not (os.path.exists(link) and
347 os.path.samefile(link, source.path)):
348 gbp.log.info('Creating symlink to %s' % source.path)
349 os.symlink(source.path, link)
351 gbp.log.warn('Orig source not a tarball, not symlinked')
353 except (gbpc.CommandExecFailed, GitRepositoryError) as err:
354 msg = err.__str__() if len(err.__str__()) else ''
355 raise GbpError("Import of %s failed: %s" % (source.path, msg))
356 except (GbpError, GitRepositoryError) as err:
357 if len(err.__str__()):
362 cleanup_tmp_tree(tmpdir)
365 gbp.log.info("Successfully imported version %s of %s" % (version, source.path))
368 if __name__ == "__main__":
369 sys.exit(main(sys.argv))
371 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: