diff options
author | Guido Guenther <agx@sigxcpu.org> | 2008-08-02 13:20:04 +0200 |
---|---|---|
committer | Guido Guenther <agx@sigxcpu.org> | 2008-08-02 13:20:04 +0200 |
commit | 414f31ab7ec5acaccfe14deb4bb235466917920b (patch) | |
tree | 6fd17347e7a5bd3f897f5de46c686573cb712f49 | |
parent | 01e10dad33fa3cc9031e399c00d9dc87939c55ed (diff) | |
parent | 0267cb847d05b02122b8ed6138486d10cbdd4b07 (diff) |
Merge commit 'debian/0.4.33' into bpo-etch
Conflicts:
debian/changelog
31 files changed, 937 insertions, 247 deletions
diff --git a/debian/changelog b/debian/changelog index 8165b686..66bc8e6f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,133 @@ +git-buildpackage (0.4.33) unstable; urgency=low + + [ Adeodato Simó ] + * [35c92a4] git-import-orig: merge upstream by tag name instead of by + branch name. + * [f1ca044] command_wrappers.py: add a GitMerge wrapper class. + + [ Guido Guenther ] + * [9bbd5d2] make symlink_orig's error message more helpful + * [26c0310] make no-dch configurable via gbp.conf + * [e6ce2df] bump standards version + * [45b060e] mention git-import-dscs + * [721068a] add "meta" to sample config file + + -- Guido Guenther <agx@sigxcpu.org> Thu, 26 Jun 2008 16:47:55 +0200 + +git-buildpackage (0.4.32) unstable; urgency=low + + * [217263e] Don't set the version number twice - makes sure git-import-dsc + doesn't use the Version: line from the message instead of the signature on + old PGP signatures (Closes: #486397) + * [063fab5] escape $s in commit messages so variable names like + $remote_fs don't get dropped silently. (Closes: #486447) + * [6008c37] don't try to cleanup in case of tag_only (Closes: #486398) + + -- Guido Guenther <agx@sigxcpu.org> Mon, 16 Jun 2008 17:54:09 +0200 + +git-buildpackage (0.4.31) unstable; urgency=low + + * [bf8738f] add --git-tag-only (Closes: #485114) + * [b06bcf0] document git-import-dscs + * [c1deeb2] add epoch to dch call (Closes: #483718) + * [6640ac7] Fix typo (Closes: #484243) + + -- Guido Guenther <agx@sigxcpu.org> Thu, 12 Jun 2008 16:53:45 +0200 + +git-buildpackage (0.4.30) unstable; urgency=low + + * [cc9c42a] Try harder to find/build the upstream tarball (Closes: + #482786) + * [e6dd31e] Help pristine-tar to find the branch name (Closes: + #481806) + + -- Guido Guenther <agx@sigxcpu.org> Thu, 29 May 2008 13:24:51 +0200 + +git-buildpackage (0.4.29) unstable; urgency=low + + * [ce152d4] git-dch: include the commit id in the changelog entry + * [ad6ff99] git-dch: print default value of --meta + * [2c1c265] git-dch: avoid extra space before "(Closes: )" + * [6ddf168] add git-import-dscs (Closes: #471580) + * [2cfbf05] move dsc handling into deb_utils + + -- Guido Guenther <agx@sigxcpu.org> Sat, 17 May 2008 22:01:49 +0200 + +git-buildpackage (0.4.28) unstable; urgency=low + + * git-buildpackage: add --git-dont-purge to leave the exported build dir + intact (Closes: #479848) - thanks to Kurt B. Kaiser for the patch + * git-dch: make --meta a config file option + * git-import-orig: fix symlink creation + * docs: missing EOF (Closes: #479726) - thanks to Sedat Dilek + + -- Guido Guenther <agx@sigxcpu.org> Mon, 12 May 2008 18:03:47 +0200 + +git-buildpackage (0.4.27) unstable; urgency=low + + * make author parsing more robust (Closes: #479263) + * fix --git-export (Closes: #479147) + + -- Guido Guenther <agx@sigxcpu.org> Sun, 04 May 2008 16:43:43 +0200 + +git-buildpackage (0.4.26) unstable; urgency=low + + * git-export=INDEX exports the index into git-export-dir + (Closes: #471568) + * make ignore-new a config file option (Closes: #466900) + * build-depend on python-dateutil (Closes: #477959) + * git-dch: + * use --no-auto-nmu + * error handling fixes + * depend on devscripts that has dch --no-auto-nmu + * gbp/config.py: make boolean options parsing more robust + * add a link to the online version of the manual + + -- Guido Guenther <agx@sigxcpu.org> Mon, 28 Apr 2008 16:36:44 +0200 + +git-buildpackage (0.4.25) unstable; urgency=low + + * create a symlink archive -> <package>_<version>.orig.tar.gz this makes + sure pristine_tar uses the correct filename for the orig.tar.gz. (Closes: + #475316) + * fix unpack_orig error reporting by adding the missing imports + * fix "pristine-tar missing" error message + + -- Guido Guenther <agx@sigxcpu.org> Fri, 18 Apr 2008 11:33:46 +0200 + +git-buildpackage (0.4.24) unstable; urgency=low + + [ Adeodato Simó ] + * Make commits from git-import-dsc get author and date from + debian/changelog. + + [ Guido Guenther ] + * add rfc822_date_to_git() this function converts a date in RFC822 + format to a string 'seconds_since_epoch tz' that can be used for eg. + GIT_AUTHOR_DATE. + * better handle broken dsc files + + -- Guido Guenther <agx@sigxcpu.org> Mon, 14 Apr 2008 14:39:37 +0200 + +git-buildpackage (0.4.23) unstable; urgency=low + + [ Frank S. Thomas ] + * docs/manpages/*.sgml: Use the citerefentry for references to other + manpages. + * Do not list the --upstream-version option twice in the synopsis + section of git-import-orig's manpage. (Closes: #472496) + + [ Guido Guenther ] + * don't pass nonexisting branches to pristine-tar (Closes: #475554) + * doc cleanups (Closes: 473610): + * mention the html manual in the manpages + * reference pristine-tar + * filter uses glob + * move conffiles section into separate sgml file + * fix doc-base section + + -- Guido Guenther <agx@sigxcpu.org> Fri, 11 Apr 2008 19:18:08 +0200 + git-buildpackage (0.4.22~bpo40+1) etch-backports; urgency=low * Rebuild for etch-backports. @@ -581,4 +711,3 @@ git-buildpackage (0.01) unstable; urgency=low * Initial release -- Guido Guenther <agx@sigxcpu.org> Tue, 12 Sep 2006 14:55:57 +0200 - diff --git a/debian/control b/debian/control index 0d45530a..0f295a8a 100644 --- a/debian/control +++ b/debian/control @@ -3,19 +3,19 @@ Section: devel Priority: optional Maintainer: Guido Guenther <agx@sigxcpu.org> Build-Depends: cdbs, debhelper (>= 5), python-dev, python-support (>= 0.3), - pychecker, gtk-doc-tools, sgml2x, docbook-utils, jade -Standards-Version: 3.7.3 + pychecker, gtk-doc-tools, sgml2x, docbook-utils, jade, python-dateutil +Standards-Version: 3.8.0 Vcs-Git: http://honk.sigxcpu.org/git/git-buildpackage.git/ -Homepage: http://sigxcpu.org/projects.html +Homepage: http://honk.sigxcpu.org/projects.html#git-buildpackage Package: git-buildpackage Architecture: all -Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, devscripts (>= 2.10.9), - git-core (>= 1:1.5.0.1-1) +Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, devscripts (>= 2.10.26), + git-core (>= 1:1.5.0.1-1), python-dateutil Suggests: git-load-dirs, pristine-tar (>= 0.5) Description: Suite to help with Debian packages in Git repositories This package contains the following tools: - * git-import-dsc: import an existing Debian source package into a git + * git-import-{dsc,dscs}: import existing Debian source packages into a git repository * git-import-orig: import a new upstream version into the git repository * git-buildpackage: build a package out of a git repository, check for local diff --git a/debian/doc-base b/debian/doc-base index 51ba88fd..a7d60d01 100644 --- a/debian/doc-base +++ b/debian/doc-base @@ -4,7 +4,7 @@ Author: Guido Guenther Abstract: git-buildpackage is a suite to help with Debian packages in Git repositories. This manual describes the utilities in this package, their configuration and possible workflows. -Section: Apps/Programming +Section: Programming Format: HTML Index: /usr/share/doc/git-buildpackage/manual-html/index.html diff --git a/debian/rules b/debian/rules index 3f973bbc..ed34eca4 100755 --- a/debian/rules +++ b/debian/rules @@ -7,7 +7,7 @@ DEB_PYTHON_CLEAN_ARGS = --all include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/python-distutils.mk -COMMANDS=git-buildpackage git-import-dsc git-import-orig git-dch +COMMANDS=git-buildpackage git-import-dsc git-import-dscs git-import-orig git-dch MANPAGES=$(patsubst %,docs/%.1,$(COMMANDS)) MANUAL=docs/manual-html PYCHECKS=$(patsubst %,%.py,$(COMMANDS)) diff --git a/docs/chapters/import.sgml b/docs/chapters/import.sgml index 9a54ae30..6b2be569 100644 --- a/docs/chapters/import.sgml +++ b/docs/chapters/import.sgml @@ -5,7 +5,6 @@ <title>Importing already existing &debian; packages</title> <para>Importing an already exsting debian package into a git repository is as easy as: <screen> -&git-import-dsc; package_0.1-1.dsc </screen> This will create a new git repository named after the imported package, put the upstream sources onto the <option>upstream-branch</option> and the @@ -26,6 +25,14 @@ cd package/ &git-import-dsc; package_0.2-1.dsc </screen> </para> + <para> +Or you can import all versions at once using &git-import-dscs;: + <screen> +&git-import-dscs; /path/to/history/package_*.dsc + </screen> +This will create a &git; repository if necessary and import all versions sorted +by version number. + </para> </sect1> <sect1 id="gbp.import.new.upstream"> @@ -82,6 +89,7 @@ cd package/ [DEFAULT] # this is the upstream-branch: upstream-branch=theupstream-branch +EOF </screen> If you then use &git-import-orig; to import new upstream sources, they will from now on end up on <emphasis>theupstream-branch</emphasis> and diff --git a/docs/chapters/intro.sgml b/docs/chapters/intro.sgml index c5a5621f..f9983bbd 100644 --- a/docs/chapters/intro.sgml +++ b/docs/chapters/intro.sgml @@ -3,7 +3,8 @@ <para> Welcome to &git-buildpackage;, a system that integrates the <ulink url="http://www.debian.org/">Debian</ulink> package build - system with <ulink url="http://git.or.cz/">Git</ulink>. + system with <ulink url="http://git.or.cz/">Git</ulink>. The current version of this manual can be found at + <ulink url="http://honk.sigxcpu.org/projects.html#git-buildpackage">here</ulink>. </para> <para> What can these tools do for you: diff --git a/docs/chapters/releases.sgml b/docs/chapters/releases.sgml index 4e1874b4..1130d1d3 100644 --- a/docs/chapters/releases.sgml +++ b/docs/chapters/releases.sgml @@ -93,9 +93,18 @@ Thanks: cool upstream </screen> would result in a changelog entry <screen> - * New upstream version (Closes: #1000) - thanks to cool upstream + * New upstream version (Closes: #1000) - thanks to cool upstream </screen> You can use multiple <option>Closes:</option> tags. +</para><para> +Often changelog entries correspond to a single &git; commit. In this case it's +convenient to include the commit id in the chagenlog entry. This can be done +via the <option>--id-length</option> option. Using +<option>--id-length</option>=<replaceable>7</replaceable> would change the above example to: +<screen> + * [571bfd4] New upstream version (Closes: #1000) - thanks to cool upstream +</screen> +This makes it much easier to see which commit actually fixed bug #1000. </para> </sect1> </chapter> diff --git a/docs/common.ent b/docs/common.ent index 28cd7d39..98974da2 100644 --- a/docs/common.ent +++ b/docs/common.ent @@ -6,6 +6,7 @@ <!ENTITY git-buildpackage "<command>git-buildpackage</command>"> <!ENTITY git-import-orig "<command>git-import-orig</command>"> <!ENTITY git-import-dsc "<command>git-import-dsc</command>"> + <!ENTITY git-import-dscs "<command>git-import-dscs</command>"> <!ENTITY git-dch "<command>git-dch</command>"> <!ENTITY gitcmd "<command>git</command>"> <!ENTITY gitkcmd "<command>gitk</command>"> diff --git a/docs/man.git-import-dscs.sgml b/docs/man.git-import-dscs.sgml new file mode 100644 index 00000000..3777e895 --- /dev/null +++ b/docs/man.git-import-dscs.sgml @@ -0,0 +1,11 @@ +<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [ + <!ENTITY % COMMON SYSTEM "common.ent"> + %COMMON; + <!ENTITY % MANPAGES SYSTEM "manpages/manpages.ent"> + %MANPAGES; +]> + +<reference> +<title>git-buildpackage Manual</title> +&man.git.importdscs; +</reference> diff --git a/docs/manpages/git-buildpackage.sgml b/docs/manpages/git-buildpackage.sgml index a0f14c13..caf8ff76 100644 --- a/docs/manpages/git-buildpackage.sgml +++ b/docs/manpages/git-buildpackage.sgml @@ -35,6 +35,8 @@ <arg><option>--git-export-dir=</option><replaceable>directory</replaceable></arg> <arg><option>--git-export=</option><replaceable>treeish</replaceable></arg> <arg><option>--git-pristine-tar</option></arg> + <arg><option>--git-dont-purge</option></arg> + <arg><option>--git-tag-only</option></arg> </cmdsynopsis> </refsynopsisdiv> <refsect1> @@ -176,7 +178,18 @@ <term><option>--git-export-dir=</option><replaceable>directory</replaceable> </term> <listitem> - <para>Export the current branch head to <replaceable>directory</replaceable> before building.</para> + <para>Export the current branch head (or the treeish object given via + <option>--git-export</option> to <replaceable>directory</replaceable> + before building.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>--git-export=</option><replaceable>treeish</replaceable> + </term> + <listitem> + <para>Instead of exporting the current branch head, export the + treeish object <replaceable>treeish</replaceable>. The special name + <replaceable>INDEX</replaceable> exports the current index.</para> </listitem> </varlistentry> <varlistentry> @@ -187,17 +200,24 @@ </listitem> </varlistentry> <varlistentry> - <term><option>--git-export=</option><replaceable>treeish</replaceable> + <term><option>--git-pristine-tar</option> </term> - <listitem> <para>Instead of exporting the current branch head export at - the treeish object <replaceable>treeish</replaceable>.</para> + <listitem> + <para>use pristine-tar to create the orig.tar.gz</para> </listitem> </varlistentry> <varlistentry> - <term><option>--git-pristine-tar</option> + <term><option>--git-dont-purge</option> </term> <listitem> - <para>use pristine-tar to create the orig.tar.gz</para> + <para>retain exported build directory after build</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>--git-tag-only</option> + </term> + <listitem> + <para>don't build, only tag and run post-tag hooks</para> </listitem> </varlistentry> </variablelist> @@ -208,9 +228,25 @@ </refsect1> <refsect1> <title>SEE ALSO</title> - - <para>git-import-dsc (1), git-import-orig (1), debuild (1), git (1), git-dch (1)</para> - + <para> + <citerefentry> + <refentrytitle>git-import-dsc</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-dscs</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-orig</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-dch</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + &man.seealso.common; + </para> </refsect1> <refsect1> <title>AUTHOR</title> diff --git a/docs/manpages/git-dch.sgml b/docs/manpages/git-dch.sgml index b9aa16bd..3a395563 100644 --- a/docs/manpages/git-dch.sgml +++ b/docs/manpages/git-dch.sgml @@ -144,6 +144,15 @@ <para>options passed on verbatim to git-log(1)</para> </listitem> </varlistentry> + <varlistentry> + <term><option>--id-length=</option><replaceable>N</replaceable> + </term> + <listitem> + <para>include <replaceable>N</replaceable> digits of the commit id in + the changelog enty. Default is to not include any commit ids at + all.</para> + </listitem> + </varlistentry> </variablelist> </refsect1> <refsect1> @@ -152,7 +161,25 @@ <refsect1> <title>SEE ALSO</title> - <para>git-buildpackage (1), git-import-dsc (1), git-import-orig (1), git (1), git_load_dirs (1)</para> + <para> + <citerefentry> + <refentrytitle>git-buildpackage</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-dsc</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-dscs</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-orig</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + &man.seealso.common; + </para> </refsect1> <refsect1> diff --git a/docs/manpages/git-import-dsc.sgml b/docs/manpages/git-import-dsc.sgml index 6fb2cecd..d2d6c10e 100644 --- a/docs/manpages/git-import-dsc.sgml +++ b/docs/manpages/git-import-dsc.sgml @@ -100,10 +100,10 @@ </listitem> </varlistentry> <varlistentry> - <term><option>--filter=</option><replaceable>filter</replaceable> + <term><option>--filter=</option><replaceable>pattern</replaceable> </term> <listitem> - <para>filter out these files during import. Can be given multiple times.</para> + <para>filter out files glob-matching pattern. Can be given multiple times.</para> </listitem> </varlistentry> <varlistentry> @@ -121,7 +121,25 @@ <refsect1> <title>SEE ALSO</title> - <para>git-buildpackage (1), git-import-orig (1), git (1), git_load_dirs (1), git-dch (1)</para> + <para> + <citerefentry> + <refentrytitle>git-import-dscs</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-buildpackage</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-orig</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-dch</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + &man.seealso.common; + </para> </refsect1> <refsect1> <title>AUTHOR</title> diff --git a/docs/manpages/git-import-dscs.sgml b/docs/manpages/git-import-dscs.sgml new file mode 100644 index 00000000..4cfa08f2 --- /dev/null +++ b/docs/manpages/git-import-dscs.sgml @@ -0,0 +1,79 @@ +<refentry id="gbp.man.git.import.dscs"> + <refentryinfo> + <address> + &dhemail; + </address> + <author> + &dhfirstname; + &dhsurname; + </author> + </refentryinfo> + <refmeta> + <refentrytitle>git-import-dscs</refentrytitle> + &dhsection; + </refmeta> + <refnamediv> + <refname>&git-import-dscs;</refname> + + <refpurpose>Import multiple versions of a Debian source packages into a Git repository</refpurpose> + </refnamediv> + <refsynopsisdiv> + <cmdsynopsis> + &git-import-dscs; + <arg><option>git-import-dsc options</option></arg> + <arg choice="plain"><replaceable>pkg_1.dsc</replaceable></arg> + <arg choice="plain"><replaceable>pkg_2.dsc</replaceable></arg> + <arg choice="plain"><replaceable>...</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + <refsect1> + <title>DESCRIPTION</title> + <para> + &git-import-dscs; imports several versions of a Debian source package into + a &git; repository. To do so it sorts the packages by their versions first + and then imports them via calling &git-import-dsc; on each package. + </para> + + <para> + If the current directory isn't a &git; repository already the repository is + created in a subdir of the current working directory, named after the first + imported package, otherwise the &git; repository in the current working + directory is being used. This allows for incremental imports. + </para> + </refsect1> + <refsect1> + <title>OPTIONS</title> + <para> + All options are passed on verbatim to &git-import-dsc;. + </para> + </refsect1> + <refsect1> + <title>SEE ALSO</title> + + <para> + <citerefentry> + <refentrytitle>git-import-dsc</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-buildpackage</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-orig</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-dch</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + &man.seealso.common; + </para> + </refsect1> + <refsect1> + <title>AUTHOR</title> + + <para>&dhusername; &dhemail;</para> + + </refsect1> +</refentry> diff --git a/docs/manpages/git-import-orig.sgml b/docs/manpages/git-import-orig.sgml index d1034eb5..1ec5ff6b 100644 --- a/docs/manpages/git-import-orig.sgml +++ b/docs/manpages/git-import-orig.sgml @@ -27,7 +27,6 @@ <arg><option>--no-dch</option></arg> <arg><option>--upstream-branch=</option><replaceable>branch_name</replaceable></arg> <arg><option>--debian-branch=</option><replaceable>branch_name</replaceable></arg> - <arg><option>--upstream-version=</option><replaceable>version</replaceable></arg> <arg><option>--sign-tags</option></arg> <arg><option>--keyid=</option><replaceable>gpg-keyid</replaceable></arg> <arg><option>--upstream-tag=</option><replaceable>tag-format</replaceable></arg> @@ -124,10 +123,10 @@ </listitem> </varlistentry> <varlistentry> - <term><option>--filter=</option><replaceable>filter</replaceable> + <term><option>--filter=</option><replaceable>pattern</replaceable> </term> <listitem> - <para>filter out these files during import. Can be given multiple times.</para> + <para>filter out files glob-matching pattern. Can be given multiple times.</para> </listitem> </varlistentry> <varlistentry> @@ -145,7 +144,25 @@ <refsect1> <title>SEE ALSO</title> - <para>git-buildpackage (1), git-import-dsc (1), git (1), git_load_dirs (1), git-dch (1)</para> + <para> + <citerefentry> + <refentrytitle>git-buildpackage</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-dsc</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-import-dscs</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git-dch</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + &man.seealso.common; + </para> </refsect1> <refsect1> diff --git a/docs/manpages/man.conffiles.sgml b/docs/manpages/man.conffiles.sgml new file mode 100644 index 00000000..29bff99e --- /dev/null +++ b/docs/manpages/man.conffiles.sgml @@ -0,0 +1,25 @@ + <title>CONFIGURATION FILES</title> + <para>Four configuration files are parsed to set defaults for the above + commandline arguments: </para> + <variablelist> + <varlistentry> + <term>/etc/git-buildpackage/gbp.conf</term> + <listitem><para>system wide configuraton</para></listitem> + </varlistentry> + <varlistentry> + <term>~/.gbp.conf</term> + <listitem><para>per user configuration</para></listitem> + </varlistentry> + <varlistentry> + <term>.gbp.conf</term> + <listitem><para>per branch configuration, can be published with the + repository</para></listitem> + </varlistentry> + <varlistentry> + <term>.git/gbp.conf</term> + <listitem><para>per repository configuration</para></listitem> + </varlistentry> + </variablelist> + <para> + See <filename>/etc/git-buildpackage/gbp.conf</filename> for an example. + </para> diff --git a/docs/manpages/man.seealso.sgml b/docs/manpages/man.seealso.sgml new file mode 100644 index 00000000..1ad8938d --- /dev/null +++ b/docs/manpages/man.seealso.sgml @@ -0,0 +1,18 @@ + <citerefentry> + <refentrytitle>debuild</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>git_load_dirs</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>pristine-tar</refentrytitle> + <manvolnum>1</manvolnum> + </citerefentry>, + <ulink url="file:///usr/share/doc/git-buildpackage/manual-html/index.html"> + <citetitle>The Git-Buildpackage Manual</citetitle></ulink> diff --git a/docs/manpages/manpages.ent b/docs/manpages/manpages.ent index ad563597..21c5bf0d 100644 --- a/docs/manpages/manpages.ent +++ b/docs/manpages/manpages.ent @@ -1,30 +1,7 @@ <!ENTITY man.git.importorig SYSTEM "git-import-orig.sgml"> <!ENTITY man.git.importdsc SYSTEM "git-import-dsc.sgml"> +<!ENTITY man.git.importdscs SYSTEM "git-import-dscs.sgml"> <!ENTITY man.git.buildpackage SYSTEM "git-buildpackage.sgml"> <!ENTITY man.git.dch SYSTEM "git-dch.sgml"> -<!ENTITY man.git.config-files " - <title>CONFIGURATION FILES</title> - <para>Four configuration files are parsed to set defaults for the above - commandline arguments: </para> - <variablelist> - <varlistentry> - <term>/etc/git-buildpackage/gbp.conf</term> - <listitem><para>system wide configuraton</para></listitem> - </varlistentry> - <varlistentry> - <term>~/.gbp.conf</term> - <listitem><para>per user configuration</para></listitem> - </varlistentry> - <varlistentry> - <term>.gbp.conf</term> - <listitem><para>per branch configuration, can be published with the - repository</para></listitem> - </varlistentry> - <varlistentry> - <term>.git/gbp.conf</term> - <listitem><para>per repository configuration</para></listitem> - </varlistentry> - </variablelist> - <para> - See <filename>/etc/git-buildpackage/gbp.conf</filename> for an example. - </para>"> +<!ENTITY man.git.config-files SYSTEM "man.conffiles.sgml"> +<!ENTITY man.seealso.common SYSTEM "man.seealso.sgml"> diff --git a/docs/manual.sgml b/docs/manual.sgml index e72ebec5..eb977536 100644 --- a/docs/manual.sgml +++ b/docs/manual.sgml @@ -29,6 +29,7 @@ <title>Command Reference</title> &man.git.buildpackage; &man.git.importdsc; + &man.git.importdscs; &man.git.importorig; &man.git.dch; </appendix> @@ -27,6 +27,7 @@ # use this for more svn-buildpackage like behaviour: #export-dir = ../build-area/ #tarball-dir = ../tarballs/ +#ignore-new = True # Options only affecting git-import-orig [git-import-orig] @@ -43,4 +44,5 @@ [git-dch] #git-log = --no-merges #snapshot-number = snapshot + 1 - +#id-length = 0 +#meta = False diff --git a/gbp/__init__.py b/gbp/__init__.py index fe0ca3dd..a345bb2e 100644 --- a/gbp/__init__.py +++ b/gbp/__init__.py @@ -1,5 +1,6 @@ # vim: set fileencoding=utf-8 : # -# (C) 2006,2007 Guido Guenther <agx@sigxcpu.org> +# (C) 2006,2007,2008 Guido Guenther <agx@sigxcpu.org> """The various things needed by git-buildpackage and friends""" +# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/command_wrappers.py b/gbp/command_wrappers.py index 91e476e1..0fa33745 100644 --- a/gbp/command_wrappers.py +++ b/gbp/command_wrappers.py @@ -8,6 +8,7 @@ git-buildpackage and friends import subprocess import sys +import os import os.path from errors import GbpError @@ -23,21 +24,35 @@ class Command(object): """ verbose = False - def __init__(self, cmd, args=[], shell=False): + def __init__(self, cmd, args=[], shell=False, extra_env=None): self.cmd = cmd self.args = args self.run_error = "Couldn't run '%s'" % (" ".join([self.cmd] + self.args)) self.shell = shell + if extra_env is not None: + self.env = os.environ.copy() + self.env.update(extra_env) + else: + self.env = None + + def __call(self, args): + """simply wraps subprocess.call so we can be verbose""" + if self.verbose: + print self.cmd, self.args, args + cmd = [ self.cmd ] + self.args + args + if self.shell: # subprocess.call only cares about the first argument if shell=True + cmd = " ".join(cmd) + return subprocess.call(cmd, shell=self.shell, env=self.env) def __run(self, args): - """run self.cmd adding args as additional arguments""" + """ + run self.cmd adding args as additional arguments + + be verbose about errors and encode them in the return value, don't pass + on exceptons + """ try: - if self.verbose: - print self.cmd, self.args, args - cmd = [ self.cmd ] + self.args + args - if self.shell: # subprocess.call only cares about the first argument if shell=True - cmd = " ".join(cmd) - retcode = subprocess.call(cmd, shell=self.shell) + retcode = self.__call(args) if retcode < 0: print >>sys.stderr, "%s was terminated by signal %d" % (self.cmd, -retcode) elif retcode > 0: @@ -50,9 +65,21 @@ class Command(object): return retcode def __call__(self, args=[]): + """run the command, convert all errors into CommandExecFailed, assumes + that the lower levels printed an error message - only usefull if you + only expect 0 as result""" if self.__run(args): raise CommandExecFailed + def call(self, args): + """like __call__ but don't use stderr and let the caller handle the return status""" + try: + ret = self.__call(args) + except OSError, e: + raise CommandExecFailed, "Execution failed:", e + return ret + + class RunAtCommand(Command): """Run a command in a specific directory""" @@ -73,7 +100,7 @@ class PristineTar(Command): def __init__(self): if not os.access(self.cmd, os.X_OK): - raise GbpError, "%s not found - cannot use pristine-tar" + raise GbpError, "%s not found - cannot use pristine-tar" % self.cmd Command.__init__(self, self.cmd) def commit(self, archive, branch): @@ -126,7 +153,7 @@ class DpkgSourceExtract(Command): """ def __init__(self): Command.__init__(self, 'dpkg-source', ['-x']) - + def __call__(self, dsc, output_dir): self.run_error = 'Couldn\'t extract "%s"' % dsc Command.__call__(self, [dsc, output_dir]) @@ -134,8 +161,8 @@ class DpkgSourceExtract(Command): class GitCommand(Command): "Mother/Father of all git commands" - def __init__(self, cmd, args=[]): - Command.__init__(self, 'git', [cmd] + args) + def __init__(self, cmd, args=[], **kwargs): + Command.__init__(self, 'git', [cmd] + args, **kwargs) class GitInitDB(GitCommand): @@ -177,6 +204,14 @@ class GitPull(GitCommand): self.run_error = 'Couldn\'t pull "%s" to "%s"' % (branch, repo) +class GitMerge(GitCommand): + """Wrap git merge""" + def __init__(self, branch, verbose=False): + verbose = [ ['--no-summary'], [] ][verbose] + GitCommand.__init__(self, 'merge', [branch] + verbose) + self.run_error = 'Couldn\'t merge from "%s"' % (branch,) + + class GitTag(GitCommand): """Wrap git tag""" def __init__(self, sign_tag=False, keyid=None): @@ -213,9 +248,9 @@ class GitRm(GitCommand): class GitCommitAll(GitCommand): """Wrap git commit to commit all changes""" - def __init__(self, verbose=False): + def __init__(self, verbose=False, **kwargs): args = ['-a'] + [ ['-q'], [] ][verbose] - GitCommand.__init__(self, cmd='commit', args=args) + GitCommand.__init__(self, cmd='commit', args=args, **kwargs) def __call__(self, msg=''): args = [ [], ['-m', msg] ][len(msg) > 0] @@ -245,4 +280,12 @@ def copy_from(orig_dir, filters=[]): raise GbpError, "Cannot copy files, pipe failed." return [ os.path.normpath(f) for f in files if files ] -# vim:et:ts=4:sw=4: + +def _test(): + import doctest + doctest.testmod() + +if __name__ == '__main__': + _test() + +# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/config.py b/gbp/config.py index c18fc283..b9948aca 100644 --- a/gbp/config.py +++ b/gbp/config.py @@ -27,9 +27,9 @@ class GbpOptionParser(OptionParser): 'cleaner' : 'debuild clean', 'debian-branch' : 'master', 'upstream-branch' : 'upstream', - 'pristine-tar' : '', # empty means False - 'sign-tags' : '', # empty means False - 'no-create-orig' : '', # empty means False + 'pristine-tar' : 'False', + 'sign-tags' : 'False', + 'no-create-orig' : 'False', 'keyid' : '', 'posttag' : '', 'debian-tag' : 'debian/%(version)s', @@ -39,6 +39,10 @@ class GbpOptionParser(OptionParser): 'git-log' : '--no-merges', 'export-dir' : '', 'tarball-dir' : '', + 'ignore-new' : 'False', + 'meta' : 'False', + 'id-length' : '0', + 'no-dch' : 'False', } config_files = [ '/etc/git-buildpackage/gbp.conf', os.path.expanduser('~/.gbp.conf'), @@ -77,8 +81,15 @@ class GbpOptionParser(OptionParser): @var help: help text @type help: string """ + default = self.config[option_name] + if kwargs.has_key('action'): + if kwargs['action'] in [ 'store_true', 'store_false'] and self.config[option_name]: + if self.config[option_name] in [ 'True', 'False' ]: + default = eval(self.config[option_name]) + else: + raise ValueError, "Boolean options must be True or False" OptionParser.add_option(self,"--%s%s" % (self.prefix, option_name), dest=dest, - default=self.config[option_name], + default=default, help=help % self.config, **kwargs) # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/deb_utils.py b/gbp/deb_utils.py index 2e7b7078..a96bb8ea 100644 --- a/gbp/deb_utils.py +++ b/gbp/deb_utils.py @@ -3,11 +3,14 @@ # (C) 2006,2007 Guido Guenther <agx@sigxcpu.org> """provides some debian source package related helpers""" -import email import commands +import email import os +import re import shutil +import sys import command_wrappers as gbpc +from errors import GbpError # When trying to parse a version-number from a dsc or changes file, these are # the valid characters. @@ -21,6 +24,82 @@ class ParseChangeLogError(Exception): """problem parsing changelog""" pass + +class DscFile(object): + """Keeps all needed data read from a dscfile""" + pkg_re = re.compile('Source:\s+(?P<pkg>.+)\s*') + version_re = re.compile("Version:\s(\d+\:)?(?P<version>[%s]+)\s*$" % debian_version_chars) + tar_re = re.compile('^\s\w+\s\d+\s+(?P<tar>[^_]+_[^_]+(\.orig)?\.tar\.(gz|bz2))') + diff_re = re.compile('^\s\w+\s\d+\s+(?P<diff>[^_]+_[^_]+\.diff.(gz|bz2))') + + def __init__(self, dscfile): + self.pkg = "" + self.tgz = "" + self.diff = "" + self.upstream_version = "" + self.dscfile = os.path.abspath(dscfile) + f = file(self.dscfile) + fromdir = os.path.dirname(os.path.abspath(dscfile)) + for line in f: + m = self.version_re.match(line) + if m and not self.upstream_version: + if '-' in m.group('version'): + self.debian_version = m.group('version').split("-")[-1] + self.upstream_version = "-".join(m.group('version').split("-")[0:-1]) + self.native = False + else: + self.native = True # Debian native package + self.upstream_version = m.group('version') + continue + m = self.pkg_re.match(line) + if m: + self.pkg = m.group('pkg') + continue + m = self.tar_re.match(line) + if m: + self.tgz = os.path.join(fromdir, m.group('tar')) + continue + m = self.diff_re.match(line) + if m: + self.diff = os.path.join(fromdir, m.group('diff')) + continue + f.close() + if not self.pkg: + raise GbpError, "Cannot parse package name from %s" % self.dscfile + elif not self.tgz: + raise GbpError, "Cannot parse archive name from %s" % self.dscfile + + def _get_version(self): + if self.native: + return self.upstream_version + else: + return "%s-%s" % (self.upstream_version, self.debian_version) + + version = property(_get_version) + + def __str__(self): + return "<%s object %s>" % (self.__class__.__name__, self.dscfile) + + +def parse_dsc(dscfile): + """parse dsc by creating a DscFile object""" + try: + dsc = DscFile(dscfile) + except IOError, err: + raise GbpError, "Error reading dsc file: %s" % err + else: + try: + if dsc.native: + print "Debian Native Package" + print "Version:", dsc.upstream_version + else: + print "Upstream version:", dsc.upstream_version + print "Debian version:", dsc.debian_version + except AttributeError: + raise GbpError, "Error parsing dsc file %s" % dscfile + return dsc + + def parse_changelog(changelog): """parse changelog file changelog""" if not os.access(changelog, os.F_OK): @@ -50,6 +129,14 @@ def is_native(cp): return [ True, False ]['-' in cp['Version']] +def has_epoch(cp): + """does the topmost version number contain an epoch""" + try: + if cp['Epoch']: + return True + except KeyError: + return False + def has_orig(cp, dir): "Check if orig.tar.gz exists in dir" try: @@ -86,4 +173,12 @@ def unpack_orig(archive, tmpdir, filters): raise GbpError return unpackArchive.dir + +def _test(): + import doctest + doctest.testmod() + +if __name__ == '__main__': + _test() + # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/errors.py b/gbp/errors.py index be92b99f..74f0a552 100644 --- a/gbp/errors.py +++ b/gbp/errors.py @@ -1,10 +1,10 @@ # vim: set fileencoding=utf-8 : # # (C) 2006,2007 Guido Guenther <agx@sigxcpu.org> -"""Thinks common to all gbp commands""" +"""Things common to all gbp commands""" class GbpError(Exception): """Generic exception raised in git-buildpackage commands""" pass -# vim:et:ts=4:sw=4: +# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/gbp/git_utils.py b/gbp/git_utils.py index 72abdd95..5f6158c6 100644 --- a/gbp/git_utils.py +++ b/gbp/git_utils.py @@ -1,11 +1,13 @@ # vim: set fileencoding=utf-8 : # -# (C) 2006,2007 Guido Guenther <agx@sigxcpu.org> +# (C) 2006,2007,2008 Guido Guenther <agx@sigxcpu.org> """provides some git repository related helpers""" import subprocess import os.path from command_wrappers import (GitAdd, GitRm, copy_from) +import dateutil.parser +import calendar class GitRepositoryError(Exception): """Exception thrown by GitRepository""" @@ -98,7 +100,7 @@ class GitRepository(object): options, '%s..%s' % (start, end), '--', paths]) if ret: - raise GitRepositoryError, "Error gettint commits %s..%s on %s" % (start, end, paths) + raise GitRepositoryError, "Error getting commits %s..%s%s" % (start, end, ["", " on %s" % paths][len(paths) > 0] ) return [ commit.strip() for commit in commits ] def show(self, id): @@ -106,8 +108,15 @@ class GitRepository(object): commit, ret = self.__git_getoutput('show', [ id ]) if ret: raise GitRepositoryError, "can't get %s" % id - return commit + for line in commit: + yield line + def write_tree(self): + """write out the current index, return the SHA1""" + tree, ret = self.__git_getoutput('write-tree') + if ret: + raise GitRepositoryError, "can't write out current index" + return tree[0].strip() def build_tag(format, version): """Generate a tag from a given format and a version""" @@ -122,17 +131,40 @@ def sanitize_version(version): def replace_source_tree(repo, src_dir, filters, verbose=False): - """ - make the current wc match what's in src_dir - @return: True if wc was modified - @rtype: boolean - """ - old = set(repo.index_files()) - new = set(copy_from(src_dir, filters)) - GitAdd()(['.']) - files = [ obj for obj in old - new if not os.path.isdir(obj)] - if files: - GitRm(verbose=verbose)(files) - return not repo.is_clean()[0] + """ + make the current wc match what's in src_dir + @return: True if wc was modified + @rtype: boolean + """ + old = set(repo.index_files()) + new = set(copy_from(src_dir, filters)) + GitAdd()(['.']) + files = [ obj for obj in old - new if not os.path.isdir(obj)] + if files: + GitRm(verbose=verbose)(files) + return not repo.is_clean()[0] + + +def rfc822_date_to_git(rfc822_date): + """Parse a date in RFC822 format, and convert to a 'seconds tz' string. + >>> rfc822_date_to_git('Thu, 1 Jan 1970 00:00:01 +0000') + '1 +0000' + >>> rfc822_date_to_git('Thu, 20 Mar 2008 01:12:57 -0700') + '1206000777 -0700' + >>> rfc822_date_to_git('Sat, 5 Apr 2008 17:01:32 +0200') + '1207407692 +0200' + """ + d = dateutil.parser.parse(rfc822_date) + seconds = calendar.timegm(d.utctimetuple()) + tz = d.strftime("%z") + return '%d %s' % (seconds, tz) + + +def _test(): + import doctest + doctest.testmod() + +if __name__ == '__main__': + _test() # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/git-buildpackage b/git-buildpackage index a11e43e6..60272d98 100755 --- a/git-buildpackage +++ b/git-buildpackage @@ -1,7 +1,7 @@ #!/usr/bin/python # vim: set fileencoding=utf-8 : # -# (C) 2006,2007 Guido Guenther <agx@sigxcpu.org> +# (C) 2006,2007,2008 Guido Guenther <agx@sigxcpu.org> # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -30,6 +30,8 @@ from gbp.command_wrappers import (GitTag, Command, RunAtCommand, CommandExecFail from gbp.config import GbpOptionParser from gbp.errors import GbpError +# when we want to reference the index in a treeish context we call it: +index_name = "INDEX" def git_archive_pipe(prefix, pipe, output, treeish): """run the git_archive pipe""" @@ -135,8 +137,8 @@ def main(argv): parser = GbpOptionParser(command=os.path.basename(argv[0]), prefix=prefix) - parser.add_option("--git-ignore-new", action="store_true", dest="ignore_new", default=False, - help="build with uncommited changes in the source tree") + parser.add_config_file_option(option_name = "ignore-new", dest="ignore_new", + help="build with uncommited changes in the source tree", action="store_true") parser.add_option("--git-verbose", action="store_true", dest="verbose", default=False, help="verbose command execution") parser.add_config_file_option(option_name="builder", dest="builder", @@ -169,6 +171,10 @@ def main(argv): help="Use pristine-tar to create .orig.tar.gz", action="store_true") parser.add_option("--git-export", dest="treeish", default=default_tree, help="export treeish object TREEISH, default is '%s'" % default_tree) + parser.add_option("--git-dont-purge", action="store_false", dest="purge", default=True, + help="retain exported build directory after build") + parser.add_option("--git-tag-only", action="store_true", dest="tag_only", default=False, + help="don't build, only tag and run post-tag hooks") (options, args) = parser.parse_args(args) if options.verbose: @@ -203,48 +209,59 @@ def main(argv): except du.ParseChangeLogError, err: raise GbpError, "Error parsing Changelog: %s" % err - output_dir = prepare_output_dir(options.export_dir) - if options.tarball_dir: - tarball_dir = options.tarball_dir - else: - tarball_dir = output_dir - - if not repo.has_treeish(options.treeish): - raise GbpError # git-ls-tree printed an error message already - # Export to another build dir if requested: - if options.export_dir: - tmp_dir = os.path.join(output_dir, "%s-tmp" % cp['Source']) - print "Exporting '%s' to '%s'" % (options.treeish, tmp_dir) - dump_tree(tmp_dir, options.treeish) - cp = du.parse_changelog(os.path.join(tmp_dir, 'debian', 'changelog')) - if du.is_native(cp): - version = cp['Debian-Version'] + if not options.tag_only: + + output_dir = prepare_output_dir(options.export_dir) + if options.tarball_dir: + tarball_dir = options.tarball_dir + else: + tarball_dir = output_dir + + # Export to another build dir if requested: + if options.export_dir: + # write a tree of the index if necessary: + if options.treeish == index_name: + tree = repo.write_tree() + else: + tree = options.treeish + if not repo.has_treeish(tree): + raise GbpError # git-ls-tree printed an error message already + tmp_dir = os.path.join(output_dir, "%s-tmp" % cp['Source']) + print "Exporting '%s' to '%s'" % (options.treeish, tmp_dir) + dump_tree(tmp_dir, tree) + cp = du.parse_changelog(os.path.join(tmp_dir, 'debian', 'changelog')) + if du.is_native(cp): + version = cp['Debian-Version'] + else: + version = cp['Upstream-Version'] + export_dir = os.path.join(output_dir, "%s-%s" % (cp['Source'], version)) + print "Moving '%s' to '%s'" % (tmp_dir, export_dir) + move_old_export(export_dir) + os.rename(tmp_dir, export_dir) + + # Get/build the orig.tar.gz if necessary: + if not du.is_native(cp): + # first look up if we have a tarball at tarball_dir + if options.tarball_dir and not du.has_orig(cp, output_dir): + print "Looking for orig tarball '%s' from '%s'" % (du.orig_file(cp), tarball_dir) + if not du.copy_orig(cp, tarball_dir, output_dir): + print "Orig tarball '%s' not found at '%s'" % (du.orig_file(cp), tarball_dir) + else: + print "Orig tarball '%s' found at '%s'" % (du.orig_file(cp), tarball_dir) + # build an orig unless the user forbidds it + if not options.no_create_orig and not du.has_orig(cp, output_dir): + if not pristine_tar_build_orig(repo, cp, output_dir, options): + git_archive_build_orig(repo, cp, output_dir, options) + + if options.export_dir: + build_dir = export_dir else: - version = cp['Upstream-Version'] - export_dir = os.path.join(output_dir, "%s-%s" % (cp['Source'], version)) - print "Moving '%s' to '%s'" % (tmp_dir, export_dir) - move_old_export(export_dir) - os.rename(tmp_dir, export_dir) - - # Get/build the orig.tar.gz if necessary: - if not du.is_native(cp): - if du.has_orig(cp, output_dir): - pass - elif options.tarball_dir: # separate tarball dir specified - print "Getting orig tarbball from %s" % tarball_dir - if not du.copy_orig(cp, tarball_dir, output_dir): - raise GbpError, "Cannot copy orig tarball from %s" % tarball_dir - elif not options.no_create_orig: - if not pristine_tar_build_orig(repo, cp, output_dir, options): - git_archive_build_orig(repo, cp, output_dir, options) - - if options.export_dir: - build_dir = export_dir - else: - build_dir = repo_dir - - RunAtCommand(options.builder, dpkg_args, shell=True)(dir=build_dir) - if options.tag: + build_dir = repo_dir + + # Finally build the package: + RunAtCommand(options.builder, dpkg_args, shell=True)(dir=build_dir) + + if options.tag or options.tag_only: try: version = cp['Version'] except KeyError: @@ -263,8 +280,9 @@ def main(argv): print >>sys.stderr, err retval = 1 - if options.export_dir and not retval: - RemoveTree(export_dir)() + if not options.tag_only: + if options.export_dir and options.purge and not retval: + RemoveTree(export_dir)() return retval @@ -1,7 +1,7 @@ #!/usr/bin/python # vim: set fileencoding=utf-8 : # -# (C) 2007 Guido Guenther <agx@sigxcpu.org> +# (C) 2007,2008 Guido Guenther <agx@sigxcpu.org> # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -30,7 +30,8 @@ from gbp.errors import GbpError from gbp.deb_utils import parse_changelog from gbp.command_wrappers import (Command, CommandExecFailed) -snapshot_re = "\s*\*\* SNAPSHOT build @(?P<commit>[a-z0-9]+)\s+\*\*" +snapshot_re = re.compile("\s*\*\* SNAPSHOT build @(?P<commit>[a-z0-9]+)\s+\*\*") +author_re = re.compile('Author: (?P<author>.*) <(?P<email>.*)>') def system(cmd): try: @@ -39,17 +40,22 @@ def system(cmd): raise GbpError -def add_changelog_entry(msg, author): +def escape_commit(msg): + return msg.replace('"','\\\"').replace("$","\$") + + +def add_changelog_entry(msg, author, email): "add aa single changelog entry" - cmd = """DEBFULLNAME="%s" dch --append -- "%s" """ % (author, msg.replace('"','\\\"')) + cmd = """DEBFULLNAME="%s" DEBEMAIL="%s" dch --no-auto-nmu --append -- "%s" """ % (author, email, escape_commit(msg)) system(cmd) def add_changelog_section(msg, distribution): "add a new changelog section" - cmd = "dch --distribution=%s -i %s" % (distribution, msg) + cmd = "dch --no-auto-nmu --distribution=%s -i %s" % (distribution, msg) system(cmd) + def fixup_trailer(): """fixup the changelog trailer's comitter and email address - it might otherwise point to the last git committer instead of the person creating @@ -57,6 +63,7 @@ def fixup_trailer(): cmd = "dch \"\"" system(cmd) + def head_commit(): """get the full sha1 of the last commit on HEAD""" commit = subprocess.Popen([ 'git-log', 'HEAD^..' ], stdout=subprocess.PIPE).stdout @@ -93,7 +100,7 @@ def mangle_changelog(changelog, cp, snapshot, sha='unknown'): print >>cw, "%(Source)s (%(MangledVersion)s) %(Distribution)s; urgency=%(urgency)s\n" % cp line = cr.readline() - if re.match(snapshot_re, line): + if snapshot_re.match(line): cr.readline() # consume the empty line line = '' @@ -139,21 +146,26 @@ def do_snapshot(changelog, next_snapshot): return snapshot, commit -def parse_commit(repo, commit,meta, short): +def get_author(commit): + """get the author from a commit message""" + for line in commit: + m = author_re.match(line) + if m: + return m.group('author'), m.group('email') + + +def parse_commit(repo, commitid, options): """parse a commit and return message and author""" - author_re = re.compile('Author: (?P<author>.*) <(?P<email>.*)>') msg = '' thanks = '' closes = '' bugs = [] - commit = repo.show(commit) - m = author_re.match(commit[1]) - if not m: + commit = repo.show(commitid) + author, email = get_author(commit) + if not author: raise GbpError, "can't parse author of commit %s" % commit - else: - author = m.group('author') - for line in commit[4:]: + for line in commit: if line.startswith(' '): # commit body line = line[4:] if line.startswith('Closes: '): @@ -161,30 +173,31 @@ def parse_commit(repo, commit,meta, short): elif line.startswith('Thanks: '): thanks = line.split(' ', 1)[1].strip() else: # normal commit message - if short and msg: + if options.short and msg: continue elif line.strip(): # don't add all whitespace lines msg += line - else: + # start of diff output: + elif line.startswith('diff '): break - if meta: + if options.meta: if bugs: - closes = ' (Closes: %s)' % ', '.join(bugs) + closes = '(Closes: %s)' % ', '.join(bugs) if thanks: thanks = ' - thanks to %s' % thanks msg += closes + thanks - return msg, author + if options.idlen: + msg = "[%s] " % commitid[0:options.idlen] + msg + return msg, (author, email) -def shortlog_to_dch(repo, commits, meta, short): +def shortlog_to_dch(repo, commits, options): """convert the changes in git shortlog format to debian changelog format""" - commit_re = re.compile('\s+(?P<msg>.*)') - author_re = re.compile('(?P<author>.*) \([0-9]+\)') author = 'Unknown' for commit in commits: - msg, author = parse_commit(repo, commit, meta, short) - add_changelog_entry(msg, author) + msg, (author, email) = parse_commit(repo, commit, options) + add_changelog_entry(msg, author, email) def guess_snapshot_commit(cp): @@ -220,10 +233,13 @@ def main(argv): help="mark as snapshot build") parser.add_option("-a", "--auto", action="store_true", dest="auto", default=False, help="autocomplete changelog from last snapshot or tag") - parser.add_option("--meta", action="store_true", dest="meta", default=False, - help="parse meta tags in commit messages") + parser.add_config_file_option(option_name="meta", dest="meta", + help="parse meta tags in commit messages, default is '%(meta)s'", action="store_true") parser.add_option("--full", action="store_false", dest="short", default=True, help="include the full commit message") + parser.add_config_file_option(option_name="id-length", dest="idlen", + help="include N digits of the commit id in the changelog entry, default is '%(id-length)s'", + type="int", metavar="N") (options, args) = parser.parse_args(argv[1:]) if options.snapshot and options.release: @@ -265,7 +281,7 @@ def main(argv): if commits: if cp['Distribution'] != "UNRELEASED" and not found_snapshot_header: add_changelog_section(distribution="UNRELEASED", msg="UNRELEASED") - shortlog_to_dch(repo, commits, meta=options.meta, short=options.short) + shortlog_to_dch(repo, commits, options) fixup_trailer() if options.snapshot: (snap, version) = do_snapshot(changelog, options.snapshot_number) @@ -275,7 +291,7 @@ def main(argv): if options.release: do_release(changelog, cp) - except GbpError, err: + except (GbpError, GitRepositoryError), err: if len(err.__str__()): print >>sys.stderr, err ret = 1 diff --git a/git-import-dsc b/git-import-dsc index 59d2c215..aece7f9c 100755 --- a/git-import-dsc +++ b/git-import-dsc @@ -23,71 +23,14 @@ import os import tempfile import glob import pipes +from email.Utils import parseaddr import gbp.command_wrappers as gbpc -from gbp.deb_utils import debian_version_chars, unpack_orig -from gbp.git_utils import build_tag, GitRepository, GitRepositoryError, replace_source_tree +from gbp.deb_utils import debian_version_chars, parse_changelog, unpack_orig, parse_dsc, DscFile +from gbp.git_utils import build_tag, GitRepository, GitRepositoryError, replace_source_tree, rfc822_date_to_git from gbp.config import GbpOptionParser from gbp.errors import GbpError -class DscFile(object): - """Keeps all needed data read from a dscfile""" - pkg_re = re.compile('Source:\s+(?P<pkg>.+)\s*') - version_re = re.compile("Version:\s(\d+\:)?(?P<version>[%s]+)\s*$" % debian_version_chars) - tar_re = re.compile('^\s\w+\s\d+\s+(?P<tar>[^_]+_[^_]+(\.orig)?\.tar\.(gz|bz2))') - diff_re = re.compile('^\s\w+\s\d+\s+(?P<diff>[^_]+_[^_]+\.diff.(gz|bz2))') - - def __init__(self, dscfile): - self.dscfile = os.path.abspath(dscfile) - f = file(self.dscfile) - fromdir = os.path.dirname(os.path.abspath(dscfile)) - for line in f: - m = self.version_re.match(line) - if m: - if '-' in m.group('version'): - self.debian_version = m.group('version').split("-")[-1] - self.upstream_version = "-".join(m.group('version').split("-")[0:-1]) - self.native = False - else: - self.native = True # Debian native package - self.upstream_version = m.group('version') - continue - m = self.pkg_re.match(line) - if m: - self.pkg = m.group('pkg') - continue - m = self.tar_re.match(line) - if m: - self.tgz = os.path.join(fromdir, m.group('tar')) - continue - m = self.diff_re.match(line) - if m: - self.diff = os.path.join(fromdir, m.group('diff')) - continue - f.close() - - -def parse_dsc(dscfile): - """parse dsc by creating a DscFile object""" - try: - dsc = DscFile(dscfile) - except IOError, err: - print >>sys.stderr, "Error reading dsc file: %s" % err - dsc = None - else: - try: - if dsc.native: - print "Debian Native Package" - print "Version:", dsc.upstream_version - else: - print "Upstream version:", dsc.upstream_version - print "Debian version:", dsc.debian_version - except AttributeError: - print >>sys.stderr, "Error parsing dsc file %s" % dscfile - dsc = None - return dsc - - def import_initial(src, dirs, options): """ import the intial version and (in the case of a non native package) create @@ -104,7 +47,7 @@ def import_initial(src, dirs, options): gbpc.GitBranch()(options.upstream_branch) if options.pristine_tar: gbpc.PristineTar().commit(os.path.join(dirs['top'], src.tgz), - options.upstream_branch) + 'refs/heads/%s' % options.upstream_branch) except gbpc.CommandExecFailed: print >>sys.stderr, "Creation of git repository failed" return False @@ -134,11 +77,18 @@ def apply_debian_patch(src, dirs, options): try: os.chdir(dirs['git']) repo = GitRepository('.') - if src.__dict__.has_key('diff') and not git_apply_patch(src.diff): + if src.diff and not git_apply_patch(src.diff): raise GbpError os.chmod('debian/rules', 0755) if not repo.is_clean()[0]: - gbpc.GitCommitAll()(msg="Imported Debian patch %s" % version) + dch = parse_changelog('debian/changelog') + name, addr = parseaddr(dch['Maintainer']) + env = { + 'GIT_AUTHOR_NAME': name, + 'GIT_AUTHOR_EMAIL': addr, + 'GIT_AUTHOR_DATE': rfc822_date_to_git(dch['Date']), + } + gbpc.GitCommitAll(extra_env=env)(msg="Imported Debian patch %s" % version) else: print "Nothing to commit, nothing imported." gitTag(build_tag(options.debian_tag, version), @@ -210,8 +160,6 @@ def main(argv): raise GbpError else: src = parse_dsc(args[0]) - if not src: - raise GbpError try: repo = GitRepository('.') diff --git a/git-import-dscs b/git-import-dscs new file mode 100755 index 00000000..8b6d99ee --- /dev/null +++ b/git-import-dscs @@ -0,0 +1,133 @@ +#!/usr/bin/python +# vim: set fileencoding=utf-8 : +# +# (C) 2008 Guido Guenther <agx@sigxcpu.org> +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +"""Import multiple dsc files in one go""" + +import sys +import re +import os +import tempfile +import glob +import pipes +import gbp.deb_utils +import gbp.command_wrappers as gbpc +from gbp.deb_utils import parse_dsc, DscFile +from gbp.config import GbpOptionParser +from gbp.errors import GbpError +from gbp.git_utils import GitRepository, GitRepositoryError + +class DpkgCompareVersions(gbpc.Command): + cmd='/usr/bin/dpkg' + + def __init__(self): + if not os.access(self.cmd, os.X_OK): + raise GbpError, "%s not found - cannot use compare versions" % self.cmd + gbpc.Command.__init__(self, self.cmd, ['--compare-versions']) + + def __call__(self, version1, version2): + self.run_error = "Couldn't compare %s with %s" % (version1, version2) + res = gbpc.Command.call(self, [ version1, 'lt', version2 ]) + if res not in [ 0, 1 ]: + raise gbpc.CommandExecFailed, "%s: bad return code %d" % (self.run_error, res) + if res == 0: + return -1 + elif res == 1: + res = gbpc.Command.call(self, [ version1, 'gt', version2 ]) + if res not in [ 0, 1 ]: + raise gbpc.CommandExecFailed, "%s: bad return code %d" % (self.run_error, res) + if res == 0: + return 1 + return 0 + + +class DscCompareVersions(DpkgCompareVersions): + def __init__(self): + DpkgCompareVersions.__init__(self) + + def __call__(self, dsc1, dsc2): + return DpkgCompareVersions.__call__(self, dsc1.version, dsc2.version) + + +class GitImportDsc(gbpc.Command): + cmd='/usr/bin/git-import-dsc' + def __init__(self, args): + if not os.access(self.cmd, os.X_OK): + raise GbpError, "%s not found - can't import packages" % self.cmd + gbpc.Command.__init__(self, self.cmd, args) + + def __call__(self, dsc): + gbpc.Command.__call__(self, [dsc.dscfile]) + + +def usage(): + print """Usage: git-import-dscs [git-import-dsc options] /path/to/dsc1 [/path/to/dsc2] ...""" + + +def main(argv): + dirs = {'top': os.path.abspath(os.curdir)} + dscs = [] + ret = 0 + dsc_cmp = DscCompareVersions() + + try: + import_args = argv[1:] + + for arg in argv[::-1]: + if arg.endswith('.dsc'): + dscs.append(parse_dsc(arg)) + import_args.remove(arg) + + if not dscs: + usage() + sys.exit(1) + + dscs.sort(cmp=dsc_cmp) + importer = GitImportDsc(import_args) + + try: + repo = GitRepository('.') + (clean, out) = repo.is_clean() + if not clean: + print >>sys.stderr, "Repository has uncommitted changes, commit these first: " + raise GbpError, out + else: + dirs['pkg'] = dirs['top'] + except GitRepositoryError: + # no git repository there yet + dirs['pkg'] = os.path.join(dirs['top'], dscs[0].pkg) + + importer(dscs[0]) + os.chdir(dirs['pkg']) + + for dsc in dscs[1:]: + importer(dsc) + + except (GbpError, gbpc.CommandExecFailed), err: + if len(err.__str__()): + print >>sys.stderr, err + ret = 1 + finally: + os.chdir(dirs['top']) + + if not ret: + print 'Everything imported under %s' % dirs['pkg'] + return ret + +if __name__ == '__main__': + sys.exit(main(sys.argv)) + +# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: diff --git a/git-import-orig b/git-import-orig index 0d0d3a65..6774a44c 100755 --- a/git-import-orig +++ b/git-import-orig @@ -25,7 +25,7 @@ import re import glob import subprocess import gbp.command_wrappers as gbpc -from gbp.deb_utils import unpack_orig +from gbp.deb_utils import parse_changelog, unpack_orig, NoChangelogError, has_epoch from gbp.git_utils import (GitRepositoryError, GitRepository, build_tag, replace_source_tree) from gbp.config import GbpOptionParser from gbp.errors import GbpError @@ -39,6 +39,26 @@ def cleanup_tmp_tree(tree): print >>sys.stderr, "Removal of tmptree %s failed." % tree +def symlink_orig(archive, pkg, version): + """ + create a symlink <pkg>_<version>.orig.tar.gz so pristine-tar will see the + correct basename + @return: archive path to be used by pristine tar + """ + if os.path.isdir(archive): + return None + ext = os.path.splitext(archive)[1] + dst = "../%s_%s.orig.tar%s" % (pkg, version, ext) + if os.path.basename(archive) != os.path.basename(dst): + try: + os.symlink(os.path.abspath(archive), dst) + except OSError, err: + raise GbpError, "Cannot symlink '%s' to '%s': %s" % (archive, dst, err[1]) + return dst + else: + return archive + + def import_upstream_tree(repo, src_dir, version, filters, verbose): """import the source uptream tree to the current branch""" try: @@ -71,6 +91,7 @@ def guess_version(archive, version_regex=r''): def main(argv): ret = 0 tmpdir = '' + pristine_orig = None parser = GbpOptionParser(command=os.path.basename(argv[0]), prefix='', usage='%prog [-u version] /path/to/upstream-version.tar.gz') @@ -81,8 +102,8 @@ def main(argv): help="verbose command execution") parser.add_option("--no-merge", dest='merge', action="store_false", default=True, help="after import dont do any merging to another branch") - parser.add_option("--no-dch", dest='run_dch', action="store_false", default=True, - help="don't call dch after the import") + parser.add_config_file_option(option_name="no-dch", dest='no_dch', + help="don't call dch after the import", action="store_true") parser.add_config_file_option(option_name="debian-branch", dest='debian_branch', help="branch the debian patch is being developed on, default is '%(debian-branch)s'") parser.add_config_file_option(option_name="upstream-branch", dest="upstream_branch", @@ -105,7 +126,6 @@ def main(argv): gitCheckoutMaster = gbpc.GitCheckoutBranch(options.debian_branch) gitShowBranch = gbpc.GitShowBranch() - gitPullUpstream = gbpc.GitPull('.', options.upstream_branch) try: if len(args) != 1: @@ -164,20 +184,29 @@ on howto create it otherwise use --upstream-branch to specify it. # archive content not in a subdir else: orig_dir = tmpdir + try: + cp = parse_changelog('debian/changelog') + pristine_orig = symlink_orig(archive, cp['Source'], version) + except NoChangelogError: + pristine_orig = archive try: filter_msg = ["", " (filtering out %s)" % options.filters][len(options.filters) > 0] - if not is_empty: + if is_empty: + print "Initial import of '%s' %s..." % (archive, filter_msg) + else: print "Importing '%s' to branch '%s'%s..." % (archive, options.upstream_branch, filter_msg) gbpc.GitCheckoutBranch(options.upstream_branch)() - else: - print "Initial import of '%s' %s..." % (archive, filter_msg) import_upstream_tree(repo, orig_dir, version, options.filters, verbose=not is_empty) if options.pristine_tar: - gbpc.PristineTar().commit(archive, options.upstream_branch) - gbpc.GitTag(options.sign_tags, options.keyid)(build_tag(options.upstream_tag, version), - msg="Upstream version %s" % version) + upstream_branch = [ options.upstream_branch, 'master' ][is_empty] + if pristine_orig: + gbpc.PristineTar().commit(pristine_orig, 'refs/heads/%s' % upstream_branch) + else: + print >>sys.stderr, "Warning: '%s' not an archive, skipping pristine-tar" % archive + tag = build_tag(options.upstream_tag, version) + gbpc.GitTag(options.sign_tags, options.keyid)(tag, msg="Upstream version %s" % version) if is_empty: gbpc.GitBranch()(options.upstream_branch) @@ -186,11 +215,16 @@ on howto create it otherwise use --upstream-branch to specify it. gitCheckoutMaster() gitShowBranch() try: - gitPullUpstream() + gbpc.GitMerge(tag)() except gbpc.CommandExecFailed: raise GbpError, """Merge failed, please resolve and run "dch -v %s-1".""" % version - if options.run_dch: - gbpc.Dch("%s-1" % version, 'New Upstream Version')() + if not options.no_dch: + epoch = '' + if os.access('debian/changelog', os.R_OK): + cp = parse_changelog('debian/changelog') + if has_epoch(cp): + epoch = '%s:' % cp['Epoch'] + gbpc.Dch("%s%s-1" % (epoch, version), 'New Upstream Version')() except gbpc.CommandExecFailed: raise GbpError, "Import of %s failed" % archive except GbpError, err: @@ -21,7 +21,7 @@ from distutils.core import setup setup(name = "git_build_package", author = 'Guido Guenther', author_email = 'agx@sigxcpu.org', - scripts = [ 'git-buildpackage', 'git-import-dsc', 'git-import-orig', 'git-dch' ], + scripts = [ 'git-buildpackage', 'git-import-dsc', 'git-import-orig', 'git-dch', 'git-import-dscs' ], packages = [ 'gbp' ], data_files = [("/etc/git-buildpackage/", ["gbp.conf" ]),], ) |