mercurial-buildpackage-0.10/0000755000000000000000000000000012001054631012704 5ustar mercurial-buildpackage-0.10/DebianPackageVersion.hx0000644000000000000000000000441611714013023017256 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // Structure for holding an expanded Debian package version number, see Debian // Policy section 5.6.2. class DebianPackageVersion { public var epoch (default,null) : Null; public var upstream (default,null) : String; public var debianRevision (default,null) : Null; public function new( v : String ) { epoch = null; debianRevision = null; // Is there a Debian revision number? var debianRevisionRegExp = ~/^(.*)-([a-z0-9+.~]+)$/i; if( debianRevisionRegExp.match( v ) ) { debianRevision = debianRevisionRegExp.matched( 2 ); // Is there an epoch? var epochRegExp = ~/^([0-9]+):(.*)$/; if( epochRegExp.match( debianRevisionRegExp.matched( 1 ) ) ) { epoch = epochRegExp.matched( 1 ); upstream = epochRegExp.matched( 2 ); } else { // No epoch. upstream = debianRevisionRegExp.matched( 1 ); } } else { // No Debian revision. // Is there an epoch? var epochRegExp = ~/^([0-9]+):(.*)$/; if( epochRegExp.match( v ) ) { epoch = epochRegExp.matched( 1 ); upstream = epochRegExp.matched( 2 ); } else { // No epoch. upstream = v; } } } public function toString() : String { if( epoch != null ) return epoch + ':' + archiveVersion(); else return archiveVersion(); } // // The full version but without epoch. Used for filename creation. // public function archiveVersion() : String { if( debianRevision != null ) return upstream + '-' + debianRevision; else return upstream; } } mercurial-buildpackage-0.10/MercurialTagVersion.hx0000644000000000000000000000474011721774357017225 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // This implementation was inspired by John Goerzen's hg-markdeb. class MercurialTagVersion { public static function main() { logger = new Script(); var usage = "Usage: " + Constants.tagVersion() + " [-V|--version]" + " [-v|--verbose] [-i|--ignore-uncommitted] [-f|--force]\n"; var options = new GetPot( neko.Sys.args() ); Util.maybeReportVersion( options, usage ); // Collect verbosity options. while( options.got( ["--verbose","-v"] ) ) ++logger.verbosity; // Should uncommitted changes be ignored? var ignore = options.got( ["-i","--ignore-uncommited"] ); // Should the tag overwrite? var force = options.got( ["-f","--force"] ); // Reject other arguments. Util.exitOnExtraneousArguments( options, usage ); // Extract package information from the changelog file. var changeLog = DebianChangeLog.parseCurrentChangeLog( logger ); // Check for presence of Mercurial directory. Mercurial.exitIfNoWorkingDirectory( "." ); // Complain if working directory is not clean. if( Mercurial.uncommittedChanges( logger ) ) { if( ! ignore ) { Util.die( "Working directory has uncommitted changes." ); } logger.info( 1, "Ignoring uncommited changes." ); } // Construct a tag for the current revision. var newTag = Util.fullTag( changeLog ); // Complain if the tag is already there. if( Mercurial.hasTag( newTag, logger ) ) { if( ! force ) { Util.die( "Tag " + newTag + " already exists." ); } logger.info( 1, "Overwriting tag " + newTag + "." ); } // Let Mercurial do the tag. var msg = Constants.tagVersion() + " added tag " + newTag; Process.runButExitOnError( "hg", [ "tag", newTag, "-f", "-m", msg ], logger ); } static var logger : Script; } mercurial-buildpackage-0.10/ProcessTwoStreamIterator.hx0000644000000000000000000000636411721774357020302 0ustar // Copyright (c) 2011, Jens Peter Secher // Copyright (c) 2012, Darren Salt // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // Structure for iterating over a Process' output. class ProcessTwoStreamIterator implements Iter { public function new( streamA : haxe.io.Input, streamB : haxe.io.Input, ? process : neko.io.Process ) { lock = new neko.vm.Lock (); pending = new neko.vm.Lock (); pendingClaimed = true; running = true; this.process = process; stream = [streamA, streamB]; thread = [neko.vm.Thread.create (runStreamA), neko.vm.Thread.create (runStreamB)]; lines = new List (); lock.release (); } // First stream, usually stdout private function runStreamA () { runStream (0); } // Second stream, usually stderr private function runStreamB () { runStream (1); } // Read from a stream, a line at a time, and queue the output private function runStream (id : Int) { while (true) { try { var line = stream[id].readLine (); lock.wait (); lines.add (line); pendingRelease (); lock.release (); } catch( e : haxe.io.Eof ) { // Assume that EOF on one stream is EOF on both lock.wait (); running = false; pendingRelease (); lock.release (); return; } catch( e : haxe.io.Error ) { // Wait 10 ms for more input to arrive. neko.Sys.sleep( 0.01 ); } } } // Release pending: input available and/or process terminated private function pendingRelease () { if (pendingClaimed) { pendingClaimed = false; pending.release (); } } // Implementation of Iterable; public function iterator() : Iterator { return this; } // Implementation of Iterator. public function next() : String { lock.wait (); var line = lines.pop (); lock.release (); return line; } // Implementation of Iterator. public function hasNext() : Bool { var length = 0; do { // Get the length. If it's non-zero, return. lock.wait (); length = lines.length; if (length > 0) { lock.release (); return true; } // Otherwise, wait for input or process termination... lock.release (); pending.wait (); pendingClaimed = true; // ... and return if the process has terminated. } while (running); return length != 0; } var stream : Array; var thread : Array; var lines : List; var lock : neko.vm.Lock; var pending : neko.vm.Lock; var pendingClaimed : Bool; var process : neko.io.Process; var running : Bool; } mercurial-buildpackage-0.10/debian/0000755000000000000000000000000012001054631014126 5ustar mercurial-buildpackage-0.10/debian/dirs0000644000000000000000000000003511714013023015010 0ustar /usr/bin /usr/share/man/man1 mercurial-buildpackage-0.10/debian/control0000644000000000000000000000224712001054037015536 0ustar Source: mercurial-buildpackage Section: devel Priority: optional Maintainer: Darren Salt Build-Depends: dpkg (>= 1.15.5.6), debhelper (>= 7), haxe (>= 1:2.4-3~) Standards-Version: 3.9.1 Vcs-Hg: http://hg.debian.org/hg/collab-maint/mercurial-buildpackage Package: mercurial-buildpackage Architecture: any Depends: mercurial, devscripts, pristine-tar (>= 1.18), neko, ${shlibs:Depends}, ${misc:Depends} Recommends: sudo, pbuilder Suggests: quilt Description: Suite to maintain Debian packages in Mercurial repository This package helps to automate the task of maintaining Debian packages by using the distributed version-control system Mercurial. The programs included are: . mercurial-importdsc: Import an existing Debian source package into a Mercurial repository. . mercurial-importorig: Import new upstream tarballs. . mercurial-pristinetar: Recreate source tarballs from the Mercurial repository so they are identical to original upstream tarballs. . mercurial-buildpackage: Build a Debian package from the Mercurial repository, either in-place or using pbuilder. . mercurial-tagversion: Mark an uploaded Debian package for future reference. mercurial-buildpackage-0.10/debian/changelog0000644000000000000000000001340712001054007016002 0ustar mercurial-buildpackage (0.10) unstable; urgency=low * Taking over this package... (Closes: #628953) * Add support for xz-compressed tarballs. (Closes: #658648) - Bump dependency on pristine-tar to >= 1.18. * Fix (most) problems with pristine tarball generation. (Closes: #626855) - Ensure that we have the source root directory in the tarball. - Ensure that the source root directory is correctly named. - Force owner, group and permissions to 0 when generating the xdelta. This should be enough to cover the usual use cases. It's fairly safe to say that anything else is going to be Fun™... * Don't spawn shells for tar. * Handle version info differently: vendor-specific version strings can be specified via a make variable, VENDOR_VERSION. Also, tidy up version checking in debian/rules and set VENDOR_VERSION to the vendor name as reported by dpkg-vendor. (Closes: #612271) * Have all commands respond to --help, -h and -?. * Put upstream tags on the upstream branch. It makes more sense to me than tagging a prior commit in the main branch. * Improved the concurrent stdout/stderr reading (referenced below). * Add -S (--source-only) to mercurial-buildpackage. * Add a note to README.txt about hacking on mercurial-buildpackage source. * Add build-arch and build-indep targets in debian/rules. (The latter is currently empty.) * Correctly quote (or unquote) hyphens in the man pages. * Add a dummy debian/watch. * Misc cleanup. [Jens Peter Secher] * Found a way to concurrently read stdout and stderr from a Process which means that there should be no more stalled build processes. * Allow successive import-dsc also when only the debian files changed. * Complain when importing tarballs that have no root directory but use dpkg-source with --no-check to allow manual tampering with the imported tarballs. -- Darren Salt Mon, 16 Jul 2012 19:05:58 +0100 mercurial-buildpackage (0.9) unstable; urgency=low * Cater for new hg commit behaviour: accept return code of 1. * Create new changelog entry before trying to merge during importorig. * Check that mercurial-buildpackage's changelog version matches the one in Constants.hx. * Bumped Standards-Version to 3.9.1, no change. -- Jens Peter Secher Sat, 07 Aug 2010 00:14:22 +0200 mercurial-buildpackage (0.8.2) unstable; urgency=low * Do not use paths containing "../" to avoid upsetting dpkg-source 1.15.7.1. -- Jens Peter Secher Fri, 30 Apr 2010 18:58:23 +0200 mercurial-buildpackage (0.8.1) unstable; urgency=low * Updated buildpackage manpage with operational outline and explained that Quilt patches are applied for format 3.0 packages. * buildpackage is now more verbose by default. * importorig now only tries to add new changelog entry if a debian/changelog already exists. -- Jens Peter Secher Sun, 28 Feb 2010 21:53:16 +0100 mercurial-buildpackage (0.8) unstable; urgency=low * For dpkg-source format 3.0 (quilt), the repository is now supposed to have all Quilt patches fully applied and the .pc directory committed. After importorig, the Quilt patches need to be applied manually. * Be more careful about precious and interfering files when processing directory entries. -- Jens Peter Secher Thu, 21 Jan 2010 23:43:03 +0100 mercurial-buildpackage (0.7) unstable; urgency=low * Only perform build-dependency check when building in-place, thanks to Eike Nicklas. * Refix #563057 which was reintroduced by not emptying Process output on low verbosity. -- Jens Peter Secher Tue, 19 Jan 2010 23:15:53 +0100 mercurial-buildpackage (0.6) unstable; urgency=low * Work around Mercurial's inability to track empty directories (which makes it harder to recreate pristine tarballs) by removing empty directories after unpacking of tarballs. -- Jens Peter Secher Mon, 18 Jan 2010 22:28:32 +0100 mercurial-buildpackage (0.5) unstable; urgency=low * Always process output from subprocesses immediately to avoid the subprocess blocking. (Closes: #563057) * Fixed usage help in tagversion. * Do not --skip-patches when unpacking because dpkg-source format 3.0 (quilt) expects the patches to be applied anyway. And unpack with --no-copy. -- Jens Peter Secher Mon, 11 Jan 2010 23:12:18 +0100 mercurial-buildpackage (0.4) unstable; urgency=low * Preserve executable mode for upstream files, thanks to Luke Cycon. * Just rely on the underscore in the upstream tarball file names to detect source name, thanks to Raúl Sánchez Siles. (Closes: #563058) -- Jens Peter Secher Tue, 05 Jan 2010 22:31:40 +0100 mercurial-buildpackage (0.3) unstable; urgency=low * Porting branches are now suported. * Always use Mercurial's internal merging mechanism to avoid arbitrary merging programs to start up; instead conflict markers are put directly in conflicting files. * Explained repository layout in manpage, and various other manpage fixes. * Better error message when tarball filenames do not follow format 3.0, thanks to Goswin von Brederlow. (Closes: #560189) -- Jens Peter Secher Wed, 23 Dec 2009 00:18:16 +0100 mercurial-buildpackage (0.2) unstable; urgency=low * The importorig program now saves xdeltas to be able to restore the pristine tarballs. * Fixed the dependency on haxe to avoid build failures. -- Jens Peter Secher Fri, 20 Nov 2009 23:37:20 +0100 mercurial-buildpackage (0.1) unstable; urgency=low * Initial package. It is a redesign of John Goerzen's hg-buildpackage. -- Jens Peter Secher Fri, 25 Sep 2009 21:09:28 +0200 mercurial-buildpackage-0.10/debian/copyright0000644000000000000000000000223011722230600016057 0ustar This is mercurial-buildpackage, a redesing and reimplementation based on hg-buildpackage written by John Goerzen. It was reimplemented in haXe September 2009 by Jens Peter Secher . The package and everything in it carries the following ISC license. ---[ ISC license begin ]--- Copyright (c) 2009-2011 Jens Peter Secher Copyright (c) 2012 Darren Salt Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ---[ ISC license end ]--- mercurial-buildpackage-0.10/debian/watch0000644000000000000000000000014111722442147015167 0ustar # Nothing to watch. # This file exists to silence tools which expect debian/watch to be present. mercurial-buildpackage-0.10/debian/rules0000755000000000000000000000177211722231102015214 0ustar #!/usr/bin/make -f # debian/rules for mercurial-buildpackage. PACKAGE := $(shell dpkg-parsechangelog | head -1 | cut -c9-) CHANGELOG := $(shell dpkg-parsechangelog | sed -e '/^Version: /! d; s/^.* //') clean: dh_testdir dh_testroot rm -f build-*-stamp $(MAKE) clean dh_clean build-stamp: dh_testdir $(MAKE) VENDOR_VERSION="$(shell dpkg-vendor --query Vendor)" touch $@ build: build-arch build-arch: build-stamp [ "$(CHANGELOG)" = $(shell echo '{UpstreamVersion}' | $(CURDIR)/macro-expand) ] build-indep: # nothing to do install: build dh_testdir dh_testroot dh_prep dh_installdirs $(MAKE) install DESTDIR=$(CURDIR)/debian/$(PACKAGE) binary-indep: build-indep install binary-arch: build-arch install dh_testdir dh_testroot dh_installchangelogs dh_installdocs README.txt dh_link dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build-indep build-arch build clean binary-indep binary-arch binary install mercurial-buildpackage-0.10/debian/source/0000755000000000000000000000000011714013023015426 5ustar mercurial-buildpackage-0.10/debian/source/format0000644000000000000000000000001511714013023016635 0ustar 3.0 (native) mercurial-buildpackage-0.10/debian/compat0000644000000000000000000000000211714013023015324 0ustar 7 mercurial-buildpackage-0.10/ProcessOutputIterator.hx0000644000000000000000000000262411715337302017634 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // Structure for iterating over a Process' output. class ProcessOutputIterator implements Iter { public function new( stream : haxe.io.Input ) { this.stream = stream; } // Implementation of Iterable; public function iterator() : Iterator { return this; } // Implementation of Iterator. public function next() : String { return line; } // Implementation of Iterator. public function hasNext() : Bool { try { line = stream.readLine(); return true; } catch( e : haxe.io.Eof ) { return false; } } var stream : haxe.io.Input; var line : String; } mercurial-buildpackage-0.10/Makefile0000644000000000000000000000576612001054262014362 0ustar # Copyright (c) 2009, Jens Peter Secher # Copyright (c) 2012, Darren Salt # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # Set this at make invocation if you want extended version strings. # For example, VENDOR_VERSION=foo results in "0.10 (foo)". VENDOR_VERSION ?= source_in := $(wildcard *.hx.in) source_generated := $(basename $(source_in)) source := $(wildcard *.hx) $(source_generated) Makefile binaries := mercurial-buildpackage mercurial-tagversion \ mercurial-importorig mercurial-importdsc \ mercurial-pristinetar mercurial-port helpers := macro-expand unittests manpages := $(binaries:=.1) HAXE = haxe -neko $@.n -cmd 'nekotools boot $@.n' -main all: $(binaries) $(manpages) mercurial-buildpackage: $(source) $(HAXE) MercurialBuildPackage mercurial-pristinetar: $(source) $(HAXE) MercurialPristineTar mercurial-tagversion: $(source) $(HAXE) MercurialTagVersion mercurial-importorig: $(source) $(HAXE) MercurialImportOrig mercurial-importdsc: $(source) $(HAXE) MercurialImportDsc mercurial-port: $(source) $(HAXE) MercurialPort testprocess: $(source) $(HAXE) TestProcess macro-expand: $(source) $(HAXE) MacroExpand mercurial-pristinetar.1: MercurialPristineTar.man macro-expand $(source) ./macro-expand < $< > $@ mercurial-buildpackage.1: MercurialBuildPackage.man macro-expand $(source) ./macro-expand < $< > $@ mercurial-importorig.1: MercurialImportOrig.man macro-expand $(source) ./macro-expand < $< > $@ mercurial-importdsc.1: MercurialImportDsc.man macro-expand $(source) ./macro-expand < $< > $@ mercurial-port.1: MercurialPort.man macro-expand $(source) ./macro-expand < $< > $@ mercurial-tagversion.1: MercurialTagVersion.man macro-expand $(source) ./macro-expand < $< > $@ test: $(source) haxe -neko $@.n -main Test -cmd 'nekotools boot $@.n' unittests: $(source) haxe -neko $@.n -main UnitTests -cmd 'nekotools boot $@.n' install: $(binaries) $(manpages) install $(binaries) $(DESTDIR)/usr/bin/ install $(manpages) $(DESTDIR)/usr/share/man/man1 check: unittests ./$< clean: rm -f *.n $(binaries) $(helpers) $(manpages) $(source_generated) # Generated sources Constants.hx: Constants.hx.in sed -e 's/@VENDOR@/'"$(VENDOR_VERSION)"'/g' <$< >$@ # Misc version: @echo "$(VERSION)" .PHONY: clean check all install version .DELETE_ON_ERROR: mercurial-buildpackage-0.10/MercurialImportOrig.man0000644000000000000000000000365611722435474017373 0ustar .TH "{ImportOrig}" "1" "December 2009" "{ImportOrig} {Version}" "User Commands" .SH NAME {ImportOrig} - Import upstream source code tarballs into .deb package Mercurial repository. .SH SYNOPSIS \fB{ImportOrig}\fR [\fIoption\fR] ... \fItarball\fR [\fItarball\fR] ... .SH DESCRIPTION Import upstream source tarballs into a Mercurial repository. The first tarball must be the main tarball, see \fBdpkg\-source\fR(1). The upstream sources are incorporated into the upstream branch, and merged into the default branch. It is possible to use \fB{ImportOrig}\fR multiple times to import several versions, but the versions must be imported sequentially starting with the earliest version. For \fBdpkg\-source\fR(1) format 3.0 (quilt), all patches are removed before the import, and you must manually reapply and refresh the patches. Finally you must commit the fully patched source, including the .pc directory. .SH OPTIONS .HP \fB\-\-version\fR, \fB\-V\fR .IP Output version and exit. .HP \fB\-\-verbose\fR, \fB\-v\fR .IP Increase verbosity level. Can be used several times. .HP \fB\-\-no\-merge\fR, \fB\-n\fR .IP Do not merge imported upstream source into the default branch. A manual \fBhg merge upstream\fR will then have to be done at a later stage. Remember to unapply all patches before the merge. .SH EXAMPLES .HP \fB{ImportOrig}\fR ../mypack_1.2.orig.tar.bz2 ../mypack_1.2.orig\-plugin.tar.gz .IP Import upstream source from two tarballs into the repository in the current directory, which requires the package to be in dpkg source package format 3.0 (quilt), see \fBdpkg\-source\fR(1). After the import, both the upstream and default branch will have the tag mypack_1.2. .SH AUTHOR Jens Peter Secher .SH THANKS The ideas for this package originates from John Goerzen's \fBhg\-buildpackage\fR. .SH SEE ALSO \fB{ImportDsc}\fR(1), \fB{BuildPackage}\fR(1), \fB{TagVersion}\fR(1), \fB{PristineTar}\fR(1), \fB{Port}\fR(1). mercurial-buildpackage-0.10/MercurialPristineTar.hx0000644000000000000000000001507411721774357017412 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class MercurialPristineTar { public static function main() { logger = new Script(); var usage = "Usage: " + Constants.pristineTar() + " [-V|--version]" + " [-v|--verbose] [version]" ; var options = new GetPot( neko.Sys.args() ); Util.maybeReportVersion( options, usage ); // Collect verbosity options. while( options.got( ["--verbose","-v"] ) ) ++logger.verbosity; // We cannot get to other branches if there are pending changes. Mercurial.exitIfUncommittedChanges( logger ); // Extract package information from the changelog file. Mercurial.switchToBranch( Constants.mainBranch(), logger ); var changeLog = DebianChangeLog.parseCurrentChangeLog( logger ); if( changeLog.version.debianRevision == null ) { Util.die( "Cannot generate pristine tarball for a native package." ); } var fileNameBase = changeLog.source + "_"; // Use a specified version or the most recent from the changelog. Util.exitOnExtraneousOptions( options, usage ); var version = options.unprocessed(); if( version == null ) { version = changeLog.version.upstream; } Util.exitOnExtraneousArguments( options, usage ); fileNameBase += version; // Find the matching tarball xdeltas, and map them to the component // name. var deltas = new Hash(); Mercurial.switchToBranch( Constants.pristineBranch(), logger ); var entries = neko.FileSystem.readDirectory( "." ); for( entry in entries ) { var versionRegExp = new EReg ( "^(" + RegExpUtil.escape( fileNameBase ) + "\\.orig" + "(-([A-Za-z0-9][-A-Za-z0-9]*))?" + "\\.tar\\.)([a-z0-9]+)\\." + Constants.pristineExtension() + "$", "" ); if( versionRegExp.match( entry ) ) { // Read the branch revision. var revision = neko.io.File.getContent ( versionRegExp.matched( 1 ) + Constants.revisionExtension() ); // We may want the root dir of the source tree in the tarball var tld = changeLog.source + "-" + version; if (neko.FileSystem.exists (versionRegExp.matched( 1 ) + Constants.dirExtension())) tld = neko.io.File.getContent (versionRegExp.matched( 1 ) + Constants.dirExtension()); // FIXME: escape & and % (at least) var escape = new EReg ("[%&]", ""); var pristineInfo = new Pristine ( versionRegExp.matched( 4 ), entry, versionRegExp.matched( 1 ) + Constants.xdeltaExtension(), revision, escape.replace (tld, "\\$1") ); var component = versionRegExp.matched( 3 ); // Main tarball wil have a null component. if( component == null ) component = "."; deltas.set( component, pristineInfo ); logger.info( 3, component + " => " + pristineInfo ); } } if( Lambda.count( deltas ) == 0 ) { die( "No xdeltas found for version " + version ); } // Extract each component from its dedicated branch and recreate the // pristine tarball from the right revision by using the xdelta in the // pristine branch. for( component in deltas.keys() ) { var pristineInfo = deltas.get( component ); var tarball = pristineInfo.tarballDelta.substr ( 0, pristineInfo.tarballDelta.lastIndexOf(".") ); logger.info( 2, "Switching to revision " + pristineInfo.revision ); logger.infos( 3, Mercurial.update( pristineInfo.revision, logger ) ); // Recreate a tarball from the component branch contents by // transforming the file names so they are rooted. var recreated = "recreated-" + tarball; var tarBaseArgs = ["--mode=0", "--owner=0", "--group=0"]; var tarArgs = tarBaseArgs.concat (["-cof", recreated]); if( component == "." ) { tarArgs = tarArgs.concat ([ "--no-recursion", "--transform", "s%^.%" + pristineInfo.directory + "%" ]); tarArgs.push( "." ); logger.info( 3, "Starting " + tarArgs.join(" ") ); var pack = new Process( "tar", tarArgs ); if( pack.process.exitCode() != 0 ) { logger.infos( 0, pack.stdouterr() ); die( "Could not recreate " + tarball ); } // Now for the rest of it... tarArgs = tarBaseArgs.concat ([ "-rof", recreated, "--transform", "s%^.%" + pristineInfo.directory + "/&%" ]); } for( entry in neko.FileSystem.readDirectory( "." ) ) { if( ! Constants.precious().match( entry ) ) { tarArgs.push( entry ); } } logger.info( 3, "Starting " + tarArgs.join(" ") ); var pack = new Process( "tar", tarArgs ); if( pack.process.exitCode() != 0 ) { logger.infos( 0, pack.stdouterr() ); die( "Could not recreate " + tarball ); } logger.infos( 3, pack.stdouterr() ); // tarball. Mercurial.switchToBranch( Constants.pristineBranch(), logger ); var args = [ "patch", "-p", pristineInfo.tarballDelta, recreated, tarball ]; logger.info( 2, "Starting xdelta " + args.join(" ") ); var xdelta = Process.runButExitOnError( "xdelta", args, logger ); logger.info( 2, "Created " + tarball ); // Use one of the pristine info to recreate the pristine compressed // tarball. var pristine = Util.pristineCompress ( tarball, pristineInfo.compressionDelta, pristineInfo.compression ); if( ! pristine ) { die( "Could not recreate pristine tarball for " + component ); } var compressedTarball = tarball + "." + pristineInfo.compression; neko.io.File.copy( compressedTarball, "../" + compressedTarball ); logger.info( 0, "Created ../" + compressedTarball ); // Cleanup. FileUtil.unlink( tarball ); FileUtil.unlink( recreated ); FileUtil.unlink( compressedTarball ); FileUtil.unlink( "bin" ); } Mercurial.switchToBranch( Constants.mainBranch(), logger ); neko.Sys.exit( 0 ); } // // Exit with an error message but swith back to main branch first. // static function die( msg : String ) { Mercurial.switchToBranch( Constants.mainBranch(), logger ); Util.die( msg ); } static var logger : Script; } mercurial-buildpackage-0.10/Iter.hx0000644000000000000000000000175711714013023014162 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. interface Iter { // For implementing Iterable. function iterator() : Iterator; // For implementing Iterator. function next() : T; // For implementing Iterator. function hasNext() : Bool; } mercurial-buildpackage-0.10/FileUtil.hx0000644000000000000000000000575711714013023015000 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class FileUtil { public static function directoryExists( path : String ) : Bool { return ( neko.FileSystem.exists( path ) && neko.FileSystem.isDirectory( path ) ); } public static function fileExists( path : String ) : Bool { return ( neko.FileSystem.exists( path ) && ! neko.FileSystem.isDirectory( path ) ); } // // Recursively delete everything reachable from the path. // Silently ignores nonexisting paths. // public static function unlink( path : String ) : Void { if( neko.FileSystem.exists( path ) ) { if( neko.FileSystem.isDirectory( path ) ) { for( entry in neko.FileSystem.readDirectory( path ) ) { unlink( path + "/" + entry ); } neko.FileSystem.deleteDirectory( path ); } else { neko.FileSystem.deleteFile( path ); } } } // // Recursively delete every empty directory reachable from the path. // Silently ignores nonexisting paths. // public static function prune( path : String ) : Void { if( neko.FileSystem.exists( path ) ) { if( neko.FileSystem.isDirectory( path ) ) { for( entry in neko.FileSystem.readDirectory( path ) ) { prune( path + "/" + entry ); } for( entry in neko.FileSystem.readDirectory( path ) ) { try { neko.FileSystem.deleteDirectory( path + "/" + entry ); } catch( e : Dynamic ) { // Not empty, ignore. } } } } } // // Recursively copy everything reachable from the path to the target // directory. The target directory must exist. // public static function copy( from : String, to : String ) { if( neko.FileSystem.exists( from ) ) { var leaf = neko.io.Path.withoutDirectory( from ); if( neko.FileSystem.isDirectory( from ) ) { var targetDir = to + "/" + leaf; neko.FileSystem.createDirectory( targetDir ); for( entry in neko.FileSystem.readDirectory( from ) ) { copy( from + "/" + entry, targetDir ); } } else { var target = to + "/" + leaf; neko.io.File.copy( from, target ); var stat = neko.FileSystem.stat( from ); var executable = (stat.mode & 0x40) == 0x40; if( executable ) { neko.Sys.command( "chmod", ["+x", target] ); } } } } } mercurial-buildpackage-0.10/Constants.hx.in0000644000000000000000000000674211721774262015660 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class Constants { public static function packageName() : String { return "mercurial-buildpackage"; } public static function upstream_version() : String { return "0.10"; } public static function vendor_version() : String { return "@VENDOR@"; } public static function version() : String { var vendor = vendor_version(); return upstream_version() + (vendor == '' ? "" : " (" + vendor + ")"); } public static function sudo() : String { return "sudo"; } public static function fakeroot() : String { return "fakeroot"; } public static function port() : String { return "mercurial-port"; } public static function pristineTar() : String { return "mercurial-pristinetar"; } public static function importOrig() : String { return "mercurial-importorig"; } public static function importDsc() : String { return "mercurial-importdsc"; } public static function tagVersion() : String { return "mercurial-tagversion"; } public static function buildPackage() : String { return "mercurial-buildpackage"; } public static function copyright() : String { return "Copyright (c) 2010, Jens Peter Secher \n" + "Copyright (c) 2012, Darren Salt "; } public static function mainBranch() : String { return "default"; } public static function upstreamBranch() : String { return "upstream"; } public static function pristineBranch() : String { return "pristine"; } public static function packageDirectory() : String { return "debian"; } public static function xdeltaExtension() : String { return "xdelta"; } public static function pristineExtension() : String { return "pristine"; } public static function revisionExtension() : String { return "revision"; } public static function dirExtension() : String { return "dir"; } public static function tagsFile() : String { return ".hgtags"; } // // Regular expression for matching files and directories that should be // ignored in an upstream tarball because they interfere with // mercurial-buildpackage and dpkg-source. // public static function interfere() : EReg { return ~/^\.(hg(ignore|tags)?|pc)$/; } // // Regular expression for matching special Mercurial files and directories // that should not be unlinked. // public static function precious() : EReg { return ~/^\.hg(ignore|tags)?$/; } // // Arguments to pass to tar for excluding special Mercurial files. // public static function tarExclude() : Array { return [ "-I.hg", "-I.hgignore", "-I"+tagsFile() ]; } // // Similarity percentage for file-move detection. // public static function similarity() : String { return "75"; } } mercurial-buildpackage-0.10/DebianPackageVersionUnitTest.hx0000644000000000000000000000341511714013023020754 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class DebianPackageVersionUnitTest extends haxe.unit.TestCase { public function testVersion() { var v = new DebianPackageVersion( "svn.20090212" ); assertEquals( v.epoch, null ); assertEquals( v.upstream, "svn.20090212" ); assertEquals( v.debianRevision, null ); } public function testEpochVersion() { var v = new DebianPackageVersion( "0:1.2+3" ); assertEquals( v.epoch, "0" ); assertEquals( v.upstream, "1.2+3" ); assertEquals( v.debianRevision, null ); } public function testVersionDebian() { var v = new DebianPackageVersion( "2008may-3.2~bpo5+1" ); assertEquals( v.epoch, null ); assertEquals( v.upstream, "2008may" ); assertEquals( v.debianRevision, "3.2~bpo5+1" ); } public function testEpochVersionDebian() { var v = new DebianPackageVersion( "2:1.2:3-23-1" ); assertEquals( v.epoch, "2" ); assertEquals( v.upstream, "1.2:3-23" ); assertEquals( v.debianRevision, "1" ); } } mercurial-buildpackage-0.10/Script.hx0000644000000000000000000000330011721774357014533 0ustar // Copyright (c) 2011, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /// A Container for a log and a verbosity level. class Script implements ILog { public function new() { verbosity = 0; logFile = null; } public function setLogFile( logFileName : String ) { #if debug if( logFile != null ) throw "logFile already set!?"; #end logFile = neko.io.File.write( logFileName, false ); } // Implements ILog. public function log( line : String ) { if( logFile != null ) logFile.writeString( line + "\n" ); } // Implements ILog. public function error( line : String ) { Util.writeError( line ); } // Implements ILog. public var verbosity : Int; // Implements ILog. public function info( level : Int, line : String ) { if( verbosity >= level ) Util.writeInfo( line ); } // Implements ILog. public function infos( level : Int, lines : Iterable ) { if( verbosity >= level ) Lambda.iter( lines, Util.writeInfo ); } var logFile : neko.io.FileOutput; } mercurial-buildpackage-0.10/MercurialImportDsc.man0000644000000000000000000000257211722435315017172 0ustar .TH "{ImportDsc}" "1" "December 2009" "{ImportDsc} {Version}" "User Commands" .SH NAME {ImportDsc} - Import exiting package into Mercurial repository. .SH SYNOPSIS \fB{ImportDsc}\fR [\fIoption\fR] ... \fIdscfile\fR .SH DESCRIPTION Import an existing source package into a Mercurial repository. The diffs and upstream sources are extracted from the contents of the .dsc file. \fB{ImportOrig}\fR(1) is called to import the upstream source into the upstream branch, which is then merged into the default branch, and the diffs are applied to the default branch. It is possible to use \fB{ImportDsc}\fR multiple times to import several versions, but the versions must be imported sequentially starting with the earliest version. .SH OPTIONS .HP \fB\-\-version\fR, \fB\-V\fR .IP Output version and exit. .HP \fB\-\-verbose\fR, \fB\-v\fR .IP Increase verbosity level. Can be used several times. .SH EXAMPLES .HP \fB{ImportDsc}\fR ../mypack_1.2\-3.dsc .IP Import package mypack version 1.2\-3 into the repository in the current directory. After the import, the repository will have the tags mypack_1.2 and mypack_1.2\-3. .SH AUTHOR Jens Peter Secher .SH THANKS The ideas for this package originates from John Goerzen's \fBhg\-buildpackage\fR. .SH SEE ALSO \fB{ImportOrig}\fR(1), \fB{BuildPackage}\fR(1), \fB{TagVersion}\fR(1), \fB{PristineTar}\fR(1), \fB{Port}\fR(1). mercurial-buildpackage-0.10/Mercurial.hx0000644000000000000000000001106711721774357015223 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class Mercurial { public static function exitIfNoWorkingDirectory( directory : String ) { // Check for presence of Mercurial directory. if( ! FileUtil.directoryExists( directory + "/.hg" ) ) { Util.die ( "Directory " + directory + " is not a valid Mercurial working directory." ); } } // // Returns true if there are uncommitted changes. // public static function uncommittedChanges( logger : ILog ) : Bool { // Check for presence of Mercurial directory. Mercurial.exitIfNoWorkingDirectory( "." ); // Are there uncommitted changes? var output = Process.runButExitOnError( "hg", ["status"], logger ); return Lambda.count( output ) > 0; } // // Aborts if we are not in a Mercurial directory or if there are uncommitted // changes. // public static function exitIfUncommittedChanges( logger : ILog ) { if( uncommittedChanges( logger ) ) { Util.die( "Working directory has uncommitted changes." ); } } // // Returns the hash of the head of a specific branch, or null if it does not // exist. // public static function branchHash( branch : String, logger : ILog ) : Null { var output = Process.runButExitOnError( "hg", ["branches"], logger ); for( line in output ) { // Match eg. "upstream 13:d2c015a5bd8e (inactive)". var r = ~/^([^ ]+) +[0-9]+:([0-9A-F]+)/i; if( r.match( line ) ) { if( branch == r.matched( 1 ) ) return r.matched( 2 ); } } return null; } public static function branchExists( branch : String, logger : ILog ) : Bool { return ( Mercurial.branchHash( branch, logger ) != null ); } // // Switch to a named branch, creating it if necessary. // public static function switchToBranch( branch : String, logger : ILog ) : Iter { // Do we have to create the branch? if( branchHash( branch, logger ) != null ) { // No, just go to the branch. return Process.runButExitOnError( "hg", ["update",branch], logger ); } Process.runButExitOnError( "hg", [ "update", "-r", "0" ], logger ); Process.runButExitOnError( "hg", [ "branch", branch ], logger ); var msg = "Created branch " + branch; return Process.runButExitOnError( "hg", [ "commit", "-m", msg ], logger, [0,1] ); } public static function branch( logger : ILog ) : String { var out = Process.runButExitOnError( "hg", [ "branch" ], logger ); if( ! out.hasNext() ) { Util.die( "Could not determine current branch." ); } return out.next(); } public static function revert( logger : ILog ) : Iter { return Process.runButExitOnError( "hg", ["revert","-a"], logger ); } // // Merge a specific revision into the current working directory by using // Mercurial's internal merging mechanism, which leaves conflict markers in // conflicting files. // public static function merge( revision : String, logger : ILog ) : Iter { neko.Sys.putEnv( "HGMERGE", "internal:merge" ); return Process.runButExitOnError( "hg", ["merge", "-f", "-r", revision], logger ); } public static function commit( message : String, logger : ILog ) : Iter { return Process.runButExitOnError( "hg", ["commit", "-m", message], logger ); } public static function update( revision : String, logger : ILog ) : Iter { return Process.runButExitOnError( "hg", ["update", "-r", revision], logger ); } public static function tag ( tag : String, msg : String, logger : ILog ) : Iter { return Process.runButExitOnError( "hg", ["tag", tag, "-m", msg ], logger ); } public static function getTags( logger : ILog ) : Iterator { // Get the existing tags. return Process.runButExitOnError( "hg", ["-q", "tags"], logger ); } public static function hasTag( tag : String, logger : ILog ) : Bool { for( t in getTags( logger ) ) { if( t == tag ) return true; } return false; } } mercurial-buildpackage-0.10/RegExpUtilUnitTest.hx0000644000000000000000000000265511714013023017005 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class RegExpUtilUnitTest extends haxe.unit.TestCase { public function testEscpaing() { assertEquals( RegExpUtil.escape( "", RegExpPlace.Whole ), "" ); assertEquals ( RegExpUtil.escape( "^a.b*c+d?e[f]g(h)i\\j$", RegExpPlace.Whole ), "\\^a\\.b\\*c\\+d\\?e\\[f\\]g\\(h\\)i\\\\j\\$" ); assertEquals ( RegExpUtil.escape( "^$" ), "^$" ); assertEquals ( RegExpUtil.escape( "^$", RegExpPlace.Initial ), "\\^$" ); assertEquals ( RegExpUtil.escape( "^$", RegExpPlace.Final ), "^\\$" ); assertEquals ( RegExpUtil.escape( "^.*+?[]()\\$", RegExpPlace.Whole ), "\\^\\.\\*\\+\\?\\[\\]\\(\\)\\\\\\$" ); } } mercurial-buildpackage-0.10/MercurialBuildPackage.man0000644000000000000000000001025511722435075017601 0ustar .TH "{BuildPackage}" "1" "December 2009" "{BuildPackage} {Version}" "User Commands" .SH NAME {BuildPackage} - Build a .deb package from source code under Mercurial control. .SH SYNOPSIS \fB{BuildPackage}\fR [\fIoption\fR] ... .SH DESCRIPTION \fB{BuildPackage}\fR builds a .deb package from within a Mercurial repository. The package is built either by use of \fBpbuilder\fR(1) or in-place, depending on the options. .SH OPTIONS .HP \fB\-\-version\fR, \fB\-V\fR .IP Output version and exit. .HP \fB\-\-verbose\fR, \fB\-v\fR .IP Increase verbosity level. Can be used several times. .HP \fB\-\-no\-check\-dependencies\fR, \fB\-d\fR .IP Do not check for missing build dependencies. .HP \fB\-\-include\-source\fR, \fB\-s\fR, \fB\-sa\fR .IP Force inclusion of upstream source. .HP \fB\-\-from\-version\fR \fIchangelogversion\fR, \fB\-f\fR \fIchangelogversion\fR .IP Include all changelog entries from \fIchangelogversion\fR. .HP \fB\-\-source\-only\fR, \fB\-S\fR .IP Build the source only. .HP \fB\-\-configfile\fR \fIpbuilderconfigfile\fR, \fB\-c\fR \fIpbuilderconfigfile\fR .IP Use \fBpbuilder\fR(1) to build package in a \fBchroot\fR(8) specified in \fIpbuilderconfigfile\fR. .SH EXAMPLES .HP \fB{BuildPackage}\fR .IP Silently build a package in-place using debian/rules and \fBdpkg\-genchanges\fR(1). The complete build log will be placed in \fR../\fIpackage\fR_\fIversion\fR_\fIarch\fR.build\fR. .HP \fB{BuildPackage}\fR \fB\-s\fR \fB\-f\fR 1.2\-3 \fB\-c\fR /home/jps/lenny\-pbuilderrc .IP Build a backport package for the Lenny release using pbuilder. The source and all changelog entries since 1.2\-3 are included in package. .SH REPOSITORY LAYOUT Let us assume that your package is called \fImypack\fR. The package repository should be created by a regular \fBhg\fR \fBinit\fR \fImypack\fR command. .P If \fImypack\fR is a native package, then your repository will only have the usual \fBdefault\fR branch and {Package} will only affect the \fB.hgtags\fR file when \fB{TagVersion}\fR(1) is invoked to tag a release of \fImypack\fR. .P If \fImypack\fR is a non-native package, then it will have a number of upstream tarballs, as specified in \fBdpkg\-source\fR(1). Let us assume that the upstream tarballs are mypack_1.0.orig.tar.gz, mypack_1.0.orig\-comp1.tar.bz2 and mypack_1.0.orig\-comp2.tar.gz, and that you therefore use package format 3.0 (quilt). {Package} will then maintain the following branches. .TP 10 mypack A branch containing the source from the main tarball. .TP comp1 A branch containing the source from the comp1 tarball. .TP comp2 A branch containing the source from the comp2 tarball. .TP pristine A branch containing additional information for recreating pristine upstream tarballs. .TP upstream The combination of all upstream tarballs, as specified in \fBdpkg\-source\fR(1). .TP default The branch for mainline package work. It will have all debian/patches applied and the quilt .pc directory included as part of the repository. .P So each upstream tarball will have its own branch which together with the \fBpristine\fR branch are used by \fB{PristineTar}\fR(1) to recreate pristine upstream tarballs. .P The \fBupstream\fR branch is used by \fB{ImportOrig}\fR(1) to merge new upstream versions into the mainline \fBdefault\fR branch; and by \fB{Port}\fR(1) to make alternative packages of selected upstream versions, for instance for backporting. .P In general, you should leave alone all the branches dealing with upsteam sources, and only work in the \fBdefault\fR branch or branches created by \fB{Port}\fR(1) for porting. .SH OPERATIONAL OUTLINE .SS In-place building .nf fakeroot debian/rules clean dpkg\-source \-i.hg \-b mypack .. debian/rules build debian/rules binary dpkg\-genchanges > ../mypack_1.0\-2_i386.changes .fi .SS Chroot building .nf fakeroot debian/rules clean dpkg\-source \-i.hg \-b mypack .. pbuilder \-\-build \-\-configfile ~/etc/sid\-pbuilderrc ../mypack_1.0\-2.dsc .fi .SH AUTHOR Jens Peter Secher .SH THANKS The ideas for this package originates from John Goerzen's \fBhg\-buildpackage\fR. .SH SEE ALSO \fBdpkg\-source\fR(1), \fBpbuilder\fR(1), \fB{ImportOrig}\fR(1), \fB{ImportDsc}\fR(1), \fB{TagVersion}\fR(1), \fB{PristineTar}\fR(1), \fB{Port}\fR(1). mercurial-buildpackage-0.10/UtilUnitTest.hx0000644000000000000000000000325211714013023015664 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class UtilUnitTest extends haxe.unit.TestCase { public function testParseTag() { var tag = "neko_1.8.0-4"; var changeLog = Util.parseTag( tag ); assertFalse( changeLog == null ); assertEquals( changeLog.source, "neko" ); assertEquals( changeLog.version.epoch, null ); assertEquals( changeLog.version.upstream, "1.8.0" ); assertEquals( changeLog.version.debianRevision, "4" ); } public function testParseNonTag() { var tag = "UPSTREAM_neko_1.8.0-4_TAG"; var changeLog = Util.parseTag( tag ); assertTrue( changeLog == null ); } public function testTagsOk() { var tags = [ "neko_1.8.0-4", "neko_1.8.0-1", "neko_1.8.0" ]; var newer = new DebianChangeLog( "neko", "1.8.1" ); assertTrue( Util.tagOk( tags.iterator(), newer ) ); var older = new DebianChangeLog( "neko", "1.7" ); assertFalse( Util.tagOk( tags.iterator(), older ) ); } } mercurial-buildpackage-0.10/ILog.hx0000644000000000000000000000254211721774357014130 0ustar // Copyright (c) 2011, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /// Interface for something that holds a log and a verbosity level. interface ILog { /// Put something in the log (which is usually a file). function log( line : String ) : Void; /// Put something on the error channel (which is usually stderr). function error( line : String ) : Void; /// The info channel (which is usually stdout) is guarded by the verbosity. /// Increasing verbosity is supposed to give more info. var verbosity (default,null) : Int; function info( level : Int, line : String ) : Void; function infos( level : Int, lines : Iterable ) : Void; } mercurial-buildpackage-0.10/UnitTests.hx0000644000000000000000000000214011715337302015216 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class UnitTests { static function main() { var r = new haxe.unit.TestRunner(); r.add( new GetPotUnitTest() ); r.add( new UtilUnitTest() ); r.add( new DebianPackageVersionUnitTest() ); r.add( new RegExpUtilUnitTest() ); if( r.run() ) { neko.Sys.exit( 0 ); } else { neko.Sys.exit( 1 ); } } } mercurial-buildpackage-0.10/README.txt0000644000000000000000000001264211721775770014435 0ustar INTRODUCTION ------------ The way to start using mercurial-buildpackage on mypack is as follows. me@home:~/deb$ hg init mypack me@home:~/deb$ cd mypack me@home:~/deb/mypack$ mercurial-importdsc ../mypack_$VERSION1.dsc me@home:~/deb/mypack$ ... me@home:~/deb/mypack$ mercurial-importdsc ../mypack_$VERSIONn.dsc me@home:~/deb/mypack$ mercurial-pristinetar -v Hack away and prepare a new version of mypack. me@home:~/deb/mypack$ mercurial-buildpackage -v me@home:~/deb/mypack$ sudo dpkg -i ../mypack_$NEWVERSION_$ARCH.deb Check that everything built fine. Then build in a clean chroot: me@home:~/deb/mypack$ mercurial-buildpackage -c ~/etc/sid-builderrc me@home:~/deb/mypack$ sudo dpkg -i ~/presults/mypack_$NEWVERSION_$ARCH.deb Check that everything works fine when built in chroot. me@home:~/deb/mypack$ lintian ~/presults/mypack_$NEWVERSION_$ARCH.changes me@home:~/deb/mypack$ debsign ~/presults/mypack_$NEWVERSION_$ARCH.changes me@home:~/deb/mypack$ dput ~/presults/mypack_$NEWVERSION_$ARCH.changes Record that new a version has been uploaded: me@home:~/deb/mypack$ fakeroot debian/rules clean me@home:~/deb/mypack$ hg commit me@home:~/deb/mypack$ mercurial-tagversion Make a backport to Lenny: me@home:~/deb/mypack$ mercurial-port lenny me@home:~/deb/mypack$ vi debian/changelog me@home:~/deb/mypack$ ... me@home:~/deb/mypack$ mercurial-buildpackage -c ~/etc/lenny-builderrc Incorporate new upstream releases: me@home:~/deb/mypack$ mercurial-importorig ../mypack_$VERSION9.orig.tar.gz me@home:~/deb/mypack$ quilt push me@home:~/deb/mypack$ quilt refresh me@home:~/deb/mypack$ quilt push me@home:~/deb/mypack$ quilt refresh And so forth... DESIGN ------ Mercurial-buildpackage is a reimplementation of the ideas in John Goerzen's hg-buildpackage. The goal for mercurial-buildpackage is to satisfy the following: 1. Only one repository. Upstream should be a branch of the repo instead of having a separate package.upstream repo. 2. Changes for backports should also be in the same repo. Solution: branch etch, branch lenny, etc. A mercurial-port command is then needed to merge the default branch into the lenny (say) branch so the backport can start. 3. Make it possible for mercurial-buildpackage to use pbuilder. 4. Consistent, easily parsable output; same format as Lintian or Piuparts. 5. mercurial-tagversion must complain if the repository has uncommited changes (unless --force). 6. Support dpkg source format 3.0. 7. Allow custom distribution (not just DEBIAN) in tags. Solution: Because each named branch tells which release (and thus implicitly which distribution) that branch pertains to, tags along each branch can just be _, like "neko_1.2.3-3", "haxe_1;2.0-4~bpo50+1", or "vi_2.1.5-2ubuntu1". 8. It must be possible to use mercurial-importdsc to incorporate the full history when converting an existing package. COMMITTING CODE CHANGES ----------------------- If you're in the collab-maint group on Alioth, you're welcome to hack on the source and directly commit changes. Use of branches for non-trivial changes is encouraged. That way, they can be tested independently and merged as needed for release. TODO ---- buildpackage should also copy build errors to .build log. buildpackage and port should complain about reserved branches. Check that every operation is properly rolled back if something goes wrong. Let mercurial-buildpackage have an option to just create the source package. Figure out how to support heuristics suggested by Goswin von Brederlow in #560189. With several tarballs, we cannot just use the directory structure, because then we cannot tell the main tarball from the components. So maybe a single --main buzz53.tgz would suffice for separation, and then use the name of the single directory at the root in each component? buildpackage should use heuristics to complain about changelog versions that look wrong in current branch, like ~bpo50 in default branch. And suggest --include-source. And buildpackage should complain about being on a reserved branch. Find a way to automate the process of taking a patch generated by dpkg-source 3.0 (quilt) and turn it into a properly named patch and clean up .pc directory. (Unless Quilt has something that does this.) Support and describe single-debian-patch mode: Convert to 3.0 (quilt) format and keep it out of mercurial: echo "3.0 (quilt)" >debian/source/format echo "debian/patches" >>.hgignore echo ".pc" >>.hgignore And then pass --single-debian-patch to mercurial-buildpackage. Outline what each binary does in terms of shell commands, eg. importorig ~= ..., quilt pop -a, hg merge -f -r upstream, hg commit, dch -v fullVersion, ... port should allude to missing use of tagversion when a tag is missing. Figure out how to incorporate Mercurial Queues as patch system. Make it possible to fix a broken pristine set, eg: hg up pristine cp ../package.orig.tar.gz . rm package.orig.tar gunzip package.orig.tar.gz xdelta delta -p recreated-package.orig.tar package.orig.tar package.orig.tar.xdelta pristine-gz gendelta ../package.orig.tar.gz package.orig.tar.gz.pristine hg commit -m 'Repair broken pristine files' Eliminate the pristine branch and instead put metadata into a special directory, which must then be ignored when generating the tarballs. Graciously handle existing changelog entries: Check that the to-be-auto-generated version matches a possibly existing one, and if it does, skip creating it. mercurial-buildpackage-0.10/RegExpPlace.hx0000644000000000000000000000156111714013023015407 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Used in RegExpUtil. // enum RegExpPlace { Initial; Final; Whole; Middle; } mercurial-buildpackage-0.10/MercurialBuildPackage.hx0000644000000000000000000001521311721774406017447 0ustar // Copyright (c) 2011, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // This implementation was inspired by John Goerzen's hg-buildpackage. class MercurialBuildPackage { public static function main() { logger = new Script(); var usage = "Usage: " + Constants.buildPackage() + " [-V|--version]" + " [-v|--verbose] [-d|--no-check-dependencies]" + " [-s|-sa|--include-source] [-f|--from-version changelogversion]" + " [-c|--configfile pbuilderconfigfile]" ; var options = new GetPot( neko.Sys.args() ); Util.maybeReportVersion( options, usage ); // Collect verbosity options. while( options.got( ["--verbose","-v"] ) ) ++logger.verbosity; // Create a build-log file. var dpkgArch = Process.runButExitOnError ( "dpkg-architecture", ["-qDEB_HOST_ARCH"], logger ); if( ! dpkgArch.hasNext() ) { Util.die( "Could not determine architecture." ); } var arch = dpkgArch.next(); // Check for presence of Mercurial directory. Mercurial.exitIfNoWorkingDirectory( "." ); // Extract package information from the changelog file. var changeLog = DebianChangeLog.parseCurrentChangeLog( logger ); var fileNameBase = "../" + changeLog.source + "_" + changeLog.version.archiveVersion(); var archFileName = fileNameBase + "_" + arch; var logFileName = archFileName + ".build"; logger.setLogFile( logFileName ); // Find out which branch we are on. var branch = Process.runButExitOnError( "hg", ["branch"], logger ); if( ! branch.hasNext() ) Util.die( "No branch information?" ); logger.info( 1, "Branch " + branch.next() ); logger.info( 2, "Building for architecture " + arch ); // Use pbuilder? var sourceOnly = options.got( ["-S","--source-only"] ); // Use pbuilder? var pbuilderConfig : String = null; if( options.got( ["-c","--configfile"] ) ) { pbuilderConfig = options.next(); if( pbuilderConfig == null ) Util.die( usage ); // No point in building if source only if( sourceOnly ) pbuilderConfig = null; } // Check for proper build dependencies. var checkDepends = ! options.got( ["-d","--no-check-dependencies"] ); if( pbuilderConfig != null && ! checkDepends ) { Util.die ( "--no-check-dependencies does not work with pbuilder." ); } if( pbuilderConfig == null && checkDepends ) { Process.runButExitOnError( "dpkg-checkbuilddeps", [], logger ); } var includeSource = options.got( ["-s","-sa","--include-source"] ); var fromVersion : String = null; if( options.got( ["-f","--from-version"] ) ) { fromVersion = options.next(); if( fromVersion == null ) Util.die( usage ); } Util.exitOnExtraneousArguments( options, usage ); // Exit if there is no upstream source tarball(s). checkUpstreamConsistency( changeLog ); // Make sure debian/rules is executable. Process.runButExitOnError( "chmod", ["+x","debian/rules"], logger ); // Call clean target. logger.info( 1, "Starting debian/rules clean." ); Process.runButExitOnError ( Constants.fakeroot(), ["debian/rules", "clean"], logger, 1 ); // TODO: make the above say this on error: //Util.die( "All build-depends for clean need to be installed." ); // Build source package excluding Mercurial stuff. dpkg-source itself // will exclude Quilt directories. var cwd = neko.Sys.getCwd(); var dpkgArgs = Constants.tarExclude().concat( [ "-i.hg", "-b", cwd ] ); logger.info( 1, "Starting dpkg-source " + dpkgArgs.join(" ") + " in .." ); Process.runButExitOnError ( "dpkg-source", dpkgArgs, logger, 0, ".." ); // Use pbuilder? if( sourceOnly ) { // nothing to do } else if( pbuilderConfig != null ) { pbuilderBuild( pbuilderConfig, fileNameBase + ".dsc" ); } else { regularBuild( includeSource, fromVersion, archFileName); } neko.Sys.exit( 0 ); } // // Exits the program if the changelog says that this package should have an // upstream source but there is no corresponding tarball. // static function checkUpstreamConsistency( changeLog : DebianChangeLog ) { if( changeLog.version.debianRevision == null ) { logger.info( 2, "Building native package." ); return; } // Check existance of an upstream main tarball. var mainTarballStem = "../" + changeLog.source + "_" + changeLog.version.upstream + ".orig.tar."; for( extension in ["gz","bz2","lzma","xz"] ) { var tarball = mainTarballStem + extension; if( FileUtil.fileExists( tarball ) ) { logger.info( 3, "Located upstream tarball " + tarball ); return; } } Util.dies ( [ "No upstream tarball " + mainTarballStem + "{gz,bz2,lzma,xz} located.", "Use " + Constants.pristineTar() + " to extract the tarball(s)." ] ); } // // Use pbuilder to build the package. // static function pbuilderBuild( configFileName : String, dscFileName : String ) { var pbuild = [ "/usr/sbin/pbuilder", "--build", "--configfile", configFileName, dscFileName ]; logger.info( 0, "Starting " + pbuild.join(" ") ); Process.runButExitOnError( Constants.sudo(), pbuild, logger, 0 ); } // // Use debian/rules and dpkg-genchanges to build the package. // static function regularBuild ( includeSource : Bool, fromVersion : String, archFileName : String ) { logger.info( 1, "Starting debian/rules build." ); Process.runButExitOnError( "debian/rules", ["build"], logger, 0 ); logger.info( 1, "Starting debian/rules binary." ); Process.runButExitOnError ( Constants.fakeroot(), ["debian/rules","binary"], logger, 0 ); // Use dpkg-genchanges to generate changes file. var changesFileName = archFileName + ".changes"; var changesArgs = []; if( includeSource ) changesArgs.push( "-sa" ); if( fromVersion != null ) changesArgs.push( "-v" + fromVersion ); logger.info( 1, "Starting dpkg-genchanges " + changesArgs.join(" ") ); var changes = Process.runButExitOnError ( "dpkg-genchanges", changesArgs, logger ); var changesFile = neko.io.File.write( changesFileName, false ); for( line in changes ) changesFile.writeString( line + "\n" ); } static var logger : Script; } mercurial-buildpackage-0.10/Util.hx0000644000000000000000000002247011721774357014215 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class Util { public static function writeOutput( line : String ) { var stdout = neko.io.File.stdout(); stdout.writeString( line ); stdout.writeString( "\n" ); stdout.flush(); } public static function writeInfo( line : String ) { writeOutput( "I: " + line ); } public static function writeWarning( line : String ) { writeOutput( "W: " + line ); } public static function writeError( line : String ) { var stderr = neko.io.File.stderr(); stderr.writeString( "E: " + line ); stderr.writeString( "\n" ); stderr.flush(); } public static function writeOutputs( lines : Iterable ) { Lambda.iter( lines, writeOutput ); } public static function writeErrors( lines : Iterable ) { Lambda.iter( lines, writeError ); } public static function writeInfos( lines : Iterable ) { Lambda.iter( lines, writeInfo ); } public static function die( error : String ) { writeError( error ); neko.Sys.exit( 1 ); } public static function dies( errors : Iterable ) { writeErrors( errors ); neko.Sys.exit( 1 ); } public static function maybeReportVersion( options : GetPot, usage : String ) { if( options.got( ["--version","-V"] ) ) { // There cannot be other arguments than --version. Util.exitOnExtraneousArguments( options, usage ); // Output the version number. Util.writeOutput( Constants.version() ); neko.Sys.exit( 0 ); } if( options.got( ["--help", "-h", "-?"] ) ) { // There cannot be other arguments than --help. Util.exitOnExtraneousArguments( options, usage ); Util.writeOutput( usage ); neko.Sys.exit( 0 ); } } public static function fullTag( changeLog : DebianChangeLog ) : String { var versionWithoutColons = StringTools.replace( changeLog.version.toString(), ":", ";" ); return changeLog.source + "_" + versionWithoutColons; } public static function upstreamTag ( changeLog : DebianChangeLog, component : String ) : String { var versionWithoutColons = StringTools.replace( changeLog.version.upstream, ":", ";" ); if( component == "." ) { return changeLog.source + "_" + versionWithoutColons; } else { return changeLog.source + "-" + component + "_" + versionWithoutColons; } } public static function componentBranch( source : String, component : String ) : String { if( component == "." ) return source; else return source + "-" + component; } // Returns false if there exist tags greater than the specified version. public static function tagOk ( tags : Iterator, pkg : DebianChangeLog ) : Bool { var next = pkg.version.toString(); for( tag in tags ) { var changeLog = parseTag( tag ); if( changeLog != null && changeLog.source == pkg.source ) { // Compare the two versions and return false if an existing // version is newer than the next version. var existing = changeLog.version.toString(); var compare = new Process ( "dpkg", ["--compare-versions", existing, "ge", next ] ); if( compare.process.exitCode() == 0 ) return false; } } // All existing versions are older. return true; } public static function parseTag( tag : String ) : Null { var parts = tag.split( "_" ); if( parts.length != 2 ) return null; return new DebianChangeLog( parts[ 0 ], parts[ 1 ] ); } public static function exitOnExtraneousOptions ( options : GetPot, usage : String ) { var unknown = options.unknown(); if( unknown != null ) { while( unknown != null ) { Util.writeError( "Extraneous option " + unknown ); unknown = options.unknown(); } die( usage ); } } public static function exitOnExtraneousArguments ( options : GetPot, usage : String ) { exitOnExtraneousOptions( options, usage ); var unprocessed = options.unprocessed(); if( unprocessed != null ) { while( unprocessed != null ) { Util.writeError( "Extraneous argument " + unprocessed ); unprocessed = options.unprocessed(); } die( usage ); } } // // Uncompress a compressed file. Returns false on error. // public static function uncompress( source : String, target : String ) : Bool { var unpack : Process = null; var gz = ~/\.gz$/; var bz = ~/\.bz2$/; var lzma = ~/\.lzma$/; var xz = ~/\.xz$/; if( gz.match( source ) ) { unpack = new Process ( "sh", ["-c","gzip -d -c "+source+" > "+target] ); } else if( bz.match( source ) ) { unpack = new Process ( "sh", ["-c","bzip2 -d -c "+source+" > "+target] ); } else if( lzma.match( source ) ) { unpack = new Process ( "sh", ["-c","lzma -d -c "+source+" > "+target] ); } else if( xz.match( source ) ) { unpack = new Process ( "sh", ["-c","xz -d -c "+source+" > "+target] ); } else { writeError( "Do not know how to uncompress " + source + "." ); return false; } // Check the unpacking process. if( unpack.process.exitCode() != 0 ) { // Process failed, abort. writeError( "Uncompressing " + source + " failed:" ); writeErrors( unpack.stdouterr() ); return false; } return true; } // // Create enough information to be able to compress a file so that it // becomes identical an original compressed file. Returns false on error. // public static function preparePristine( source : String, target : String ) : Bool { var pristine : Process = null; var gz = ~/\.gz$/; var bz = ~/\.bz2$/; var lzma = ~/\.lzma$/; var xz = ~/\.xz$/; if( gz.match( source ) ) { pristine = new Process ( "pristine-gz", ["gendelta",source,target] ); } else if( bz.match( source ) ) { pristine = new Process ( "pristine-bz2", ["gendelta",source,target] ); } else if( lzma.match( source ) ) { writeWarning( "Cannot guarantee recreation of lzma files." ); writeWarning( "See pristine-tar manual." ); pristine = new Process( "touch", [target] ); } else if( xz.match( source ) ) { pristine = new Process ( "pristine-xz", ["gendelta",source,target] ); } else { writeError( "Do not know how to handle " + source ); return false; } // Check the unpacking process. if( pristine.process.exitCode() != 0 ) { // Process failed, abort. writeError( "pristine-{gz,bz2,xz} " + source + " failed:" ); writeErrors( pristine.stdouterr() ); return false; } return true; } // // Recreate a compressed file using previously created information and the // uncompressed version. Returns false on error. // public static function pristineCompress ( source : String, delta : String, extension : String ) : Bool { var pristine : Process = null; switch( extension ) { case "gz": pristine = new Process ( "pristine-gz", ["gengz",delta,source] ); case "bz2": pristine = new Process ( "pristine-bz2", ["genbz2",delta,source] ); case "lzma": writeWarning( "Cannot guarantee pristine lzma files." ); pristine = new Process ( "sh", ["-c","lzma -c "+source+" > "+source+".lzma"] ); case "xz": writeWarning( "Cannot guarantee pristine xz files." ); pristine = new Process ( "pristine-xz", ["genxz",delta,source] ); default: writeError( "Do not know how to handle " + extension ); return false; } // Check the unpacking process. if( pristine.process.exitCode() != 0 ) { // Process failed, abort. writeError( "pristine-{gz,bz2,xz} " + source + " failed:" ); writeErrors( pristine.stdouterr() ); return false; } return true; } // // Extract a tarball into a directory (which must exist). Returns false on // error. // public static function extract( tarball : String, directory : String ) { var unpack : Process = null; var tgz = ~/\.tar\.gz$/; var tbz = ~/\.tar\.bz2$/; var tlzma = ~/\.tar\.lzma$/; var txz = ~/\.tar\.xz$/; if( tgz.match( tarball ) ) { unpack = new Process( "tar", ["xCfz",directory,tarball] ); } else if( tbz.match( tarball ) ) { unpack = new Process( "tar", ["xCfj",directory,tarball] ); } else if( tlzma.match( tarball ) ) { unpack = new Process ( "tar", ["xC",directory,"--lzma","-f",tarball] ); } else if( txz.match( tarball ) ) { unpack = new Process ( "tar", ["xC",directory,"--xz","-f",tarball] ); } else { writeError( "Do not know how to unpack " + tarball + "." ); return false; } // Check the unpacking process. if( unpack.process.exitCode() != 0 ) { // Process failed, abort. writeError( "Unpacking " + tarball + " failed:" ); writeErrors( unpack.stdouterr() ); return false; } return true; } } mercurial-buildpackage-0.10/RegExpUtil.hx0000644000000000000000000000352111714013023015276 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class RegExpUtil { // // Create an escaped string that can be used in regular-expression // construction so that it matches the literal string. The place argument // decides whether an initial ^ and a final $ should be escaped. // public static function escape( literal : String, ?place : RegExpPlace ) : String { if( place == null ) place = RegExpPlace.Middle; var escaped = new StringBuf(); for( i in 0...literal.length ) { var backslash = false; switch( literal.charAt( i ) ) { case ".", "*", "+", "?", "[", "]", "(", ")", "\\": backslash = true; case "^": if ( i == 0 && ( place == RegExpPlace.Initial || place == RegExpPlace.Whole ) ) { backslash = true; } case "$": if ( i == literal.length-1 && ( place == RegExpPlace.Final || place == RegExpPlace.Whole ) ) { backslash = true; } } if( backslash ) escaped.add( "\\" ); escaped.addSub( literal, i, 1 ); } return escaped.toString(); } } mercurial-buildpackage-0.10/MercurialImportDsc.hx0000644000000000000000000002215711721774357017052 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // This implementation was inspired by John Goerzen's hg-importdsc. typedef Dsc = { var dir : String; var changeLog : DebianChangeLog; var diff : String; var balls : Array; }; class MercurialImportDsc { public static function main() { logger = new Script(); var dscFileName = parseCommandLine(); var dsc = parseDsc( dscFileName ); Mercurial.exitIfUncommittedChanges( logger ); // Check that the new version is not already imported. if( Mercurial.hasTag( Util.fullTag( dsc.changeLog ), logger ) ) { Util.die ( "Version " + dsc.changeLog.version + " already exists in repository." ); } // Abort if new version is already incorporated. if( ! Util.tagOk( Mercurial.getTags( logger ), dsc.changeLog ) ) { Util.die ( "Version " + dsc.changeLog.version + " is not newer than existing Debian versions." ); } try { // Is there a Debian diff? if( dsc.diff.length > 0 ) processUpstream( dsc ); // Import tarballs. importDsc( dscFileName ); // Make sure debian/rules is executable. Process.runButExitOnError( "chmod", ["+x","debian/rules"], logger ); // Add and remove files from dsc, but do a lot to detect renames. logger.info( 1, "Starting hg addremove -s " + Constants.similarity() ); var addremove = new Process ( "hg", [ "addremove", "-s", Constants.similarity() ] ); if( addremove.process.exitCode() != 0 ) { Util.writeError( "addremove failed:" ); logger.infos( 0, addremove.stdouterr() ); throw "Addremove dsc failed."; } logger.infos( 2, addremove.stdouterr() ); // Commit the new dsc contents. logger.info( 2, "Starting hg commit" ); var msg = Constants.importDsc() + " imported " + dsc.changeLog.version; var commit = new Process( "hg", [ "commit", "-m", msg ] ); if( commit.process.exitCode() != 0 ) { Util.writeError( "commit failed:" ); logger.infos( 0, commit.stdouterr() ); throw "Commit dsc failed."; } logger.infos( 2, commit.stdouterr() ); } catch( e : Dynamic ) { Util.writeError( Std.string( e ) ); logger.info( 0, "Reverting default branch to state before import." ); Mercurial.revert( logger ); neko.Sys.exit( 1 ); } // Put a new tag in default branch. logger.info( 1, "Tagging with " + Util.fullTag( dsc.changeLog ) ); var tag = Util.fullTag( dsc.changeLog ); var msg = Constants.importDsc() + " added tag " + tag; var tagger = Mercurial.tag( tag, msg, logger ); logger.infos( 2, tagger ); } // // Setup global variables and abort if something is wrong with the command // line. Returns the dsc file name. // static function parseCommandLine() : String { var usage = "Usage: " + Constants.importDsc() + " [-V|--version]" + " [-v|--verbose] dscFile"; var options = new GetPot( neko.Sys.args() ); Util.maybeReportVersion( options, usage ); // Collect verbosity options. while( options.got( ["--verbose","-v"] ) ) ++logger.verbosity; // Reject other options. Util.exitOnExtraneousOptions( options, usage ); // Get the dsc file name. var dscFileName = options.unprocessed(); if( dscFileName == null ) Util.die( usage ); Util.exitOnExtraneousArguments( options, usage ); // Check that the dsc file exists. if( ! FileUtil.fileExists( dscFileName ) ) { Util.die( "File " + dscFileName + " does not exist." ); } return dscFileName; } static function processUpstream( dsc : Dsc ) { logger.info( 1, "Processing upstream tarball(s)." ); var args : Array = [ "--no-merge" ]; for( ball in dsc.balls ) args.push( dsc.dir + "/" + ball ); for( i in 0 ... logger.verbosity-1 ) args.push( "-v" ); var output = Process.runButExitOnError( Constants.importOrig(), args, logger ); // Filter out "to pull in new version" from importorig. for( line in output ) { var pullInUpstream = ~/to pull in new version/; if( ! pullInUpstream.match( line ) ) logger.info( 1, line ); } } static function parseDsc( dscFileName : String ) : Dsc { // Extract the source and version info. var dsc = neko.io.File.getContent( dscFileName ); // Get the source from dsc contents. var sourceRegExp = ~/^Source:[ \t]+(.+)$/m; if( ! sourceRegExp.match( dsc ) ) { Util.die( "File " + dscFileName + " does not contain source info." ); } var source = sourceRegExp.matched( 1 ); // Get the version from dsc contents. var versionRegExp = ~/^Version:[ \t]+(.+)$/m; if( ! versionRegExp.match( dsc ) ) { Util.die( "File " + dscFileName + " does not contain version info." ); } var version = versionRegExp.matched( 1 ); // Get the dpkg format. var formatRegExp = ~/^Format: (.*)$/m; if( ! formatRegExp.match( dsc ) ) { Util.die ( "File " + dscFileName + " does not contain format info." ); } var format = formatRegExp.matched( 1 ); logger.info( 1, "Source format " + format ); // Get the tarball file names. var balls = new Array(); var diff = ""; if( format == "1.0" ) { var origRegExp = ~/ ([^ ]+\.tar\.gz)$/m; if( origRegExp.match( dsc ) ) { var ball = origRegExp.matched( 1 ); logger.info( 1, "Tarball " + ball ); balls.push( ball ); var diffRegExp = ~/ ([^ ]+\.diff\.gz)$/m; if( diffRegExp.match( dsc ) ) { diff = diffRegExp.matched( 1 ); logger.info( 1, "Diff " + diff ); } } } else if( format == "3.0 (native)" ) { var origRegExp = ~/ ([^ ]+\.tar\.(gz|bz2|lzma|xz))$/m; if( origRegExp.match( dsc ) ) { var ball = origRegExp.matched( 1 ); balls.push( ball ); logger.info( 1, "Tarball " + ball ); } } else if( format == "3.0 (quilt)" ) { // Find the debian diff. var diffRegExp = ~/ ([^ ]+\.debian\.tar\.(gz|bz2|lzma|xz))$/m; if( ! diffRegExp.match( dsc ) ) { Util.die( "No debian diff in dsc file." ); } diff = diffRegExp.matched( 1 ); logger.info( 1, "Debian tarball " + diff ); // Find the main tarball. var mainRegExp = ~/ ([^ ]+\.orig\.tar\.(gz|bz2|lzma|xz))$/m; if( mainRegExp.match( dsc ) ) { var main = mainRegExp.matched( 1 ); logger.info( 1, "Main tarball " + main ); balls.push( main ); // Collect additional tarballs. var searchable = dsc; while( searchable.length > 0 ) { var componentRegExp = ~/ ([^ ]+\.orig-[A_Za-z0-9][-A_Za-z0-9]*\.tar\.(gz|bz2|lzma|xz))$/m; if( componentRegExp.match( searchable ) ) { var ball = componentRegExp.matched( 1 ); if( ! Lambda.has( balls, ball ) ) { logger.info( 1, "Additional tarball " + ball ); balls.push( ball ); searchable = componentRegExp.matchedRight(); } else { // Stop the search. searchable = ""; } } else { // Stop the search. searchable = ""; } } } } if( balls.length == 0 ) { // Search for Util.die( "No source ball in dsc file." ); } return { dir: neko.io.Path.directory( dscFileName ), changeLog: new DebianChangeLog( source, version ), diff: diff, balls: balls }; } static function importDsc( dscFileName : String ) { // Delete everything except the Mercurial and Quilt files. for( entry in neko.FileSystem.readDirectory( "." ) ) { if( ! Constants.precious().match( entry ) ) FileUtil.unlink( entry ); } // Make sure the dsc file has an absolute path. dscFileName = neko.FileSystem.fullPath( dscFileName ); // Use dpkg-source to unpack everything in a temporary directory. The // path cannot contain ".." because dpkg-source will complain about it. logger.info( 1, "Importing dsc." ); var tmpDir = neko.FileSystem.fullPath( neko.Sys.getCwd() + ".." ) + "/,,importdsc-" + neko.Sys.time(); var dpkgArgs = [ "--no-check", "--no-copy", "-x", dscFileName, tmpDir ]; logger.info( 2, "Starting dpkg-source " + dpkgArgs.join(" ") + " in .." ); logger.infos( 3, Process.runButExitOnError( "dpkg-source", dpkgArgs, logger, ".." ) ); // Delete empty directories because they are not tracked by Mercurial. FileUtil.prune( tmpDir ); // Move the unpacked source back into the root, unless it is a Mercurial // file. var entries = neko.FileSystem.readDirectory( tmpDir ); for( entry in entries ) { if( ! Constants.precious().match( entry ) ) { logger.info( 3, "Copying " + tmpDir + "/" + entry ); FileUtil.copy( tmpDir + "/" + entry, "." ); } } logger.info( 2, "Deleting " + tmpDir ); FileUtil.unlink( tmpDir ); } static var logger : Script; } mercurial-buildpackage-0.10/MercurialImportOrig.hx0000644000000000000000000004723211721774357017242 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // A component is either self-titled, or named "." if it is the main component. // typedef Component = { var component : String; var tarball : String; } // // The distilled information extracted from the list of tarball filenames to // extract. The main component is named ".", and the rest (if any) are // self-titled. The changlelog is filled with the remaining version information // they have in common. // typedef Upstream = { var components : Array; var changeLog : DebianChangeLog; var noMerge : Bool; }; class MercurialImportOrig { public static function main() { logger = new Script(); // It must be possible to switch branch, so the working directory has to // be clean. Mercurial.exitIfUncommittedChanges( logger ); Mercurial.switchToBranch( Constants.mainBranch(), logger ); var upstream : Upstream = parseCommandLine(); var version = upstream.changeLog.version.upstream; if( FileUtil.fileExists( "debian/changelog" ) ) { // Make sure the changelog is readable. DebianChangeLog.parseCurrentChangeLog( logger ); } // Put each tarball in its own branch. for( component in upstream.components ) { // Check that the component has not already been imported. var name = component.component; var tag = Util.upstreamTag( upstream.changeLog, name ); if( Mercurial.hasTag( tag, logger ) ) { logger.info( 0, "Skipping " + tag + ": already imported." ); continue; } xdeltaComponent( component, upstream ); } // Create a composition of all the components in the upstream branch. // Main upstream tarball must be cleaned from excess directories, namely // the debian directory and each of the compnent directories. var excess = []; for( component in upstream.components ) { var name = component.component; if( name == "." ) name = Constants.packageDirectory(); excess.push( name ); } try { var out = Mercurial.switchToBranch( Constants.upstreamBranch(), logger ); logger.infos( 3, out ); // Delete everything except the Mercurial files. for( entry in neko.FileSystem.readDirectory( "." ) ) { var mercurial = ~/^\.hg$/; if( ! mercurial.match( entry ) ) FileUtil.unlink( entry ); } for( component in upstream.components ) { var name = component.component; var branch = Util.upstreamTag( upstream.changeLog, name ); var root = extractComponent( component ); // TODO: cleanup if error. if( root == null ) throw "Extract " + name + " failed."; if( name == "." ) { for( inway in excess ) { if( neko.FileSystem.exists( inway ) ) { logger.info ( 1, "Removing excess " + inway + " directory from upstream." ); try { FileUtil.unlink( inway ); } catch( e : Dynamic ) { throw "Removing " + inway + ": " + Std.string(e); } } } } } // Add and remove files from the combined components, but do a lot // to detect renames. var addremove = new Process ( "hg", [ "addremove", "-s", Constants.similarity() ] ); if( addremove.process.exitCode() != 0 ) { Util.writeError( "addremove failed:" ); logger.infos( 0, addremove.stdouterr() ); throw "addremove failed."; } logger.infos( 2, addremove.stdouterr() ); // Commit the combined component version. var msg = Constants.importOrig() + " imported " + upstream.changeLog.source + " version " + upstream.changeLog.version.upstream; var commit = new Process( "hg", [ "commit", "-m", msg ] ); var output = Lambda.array( commit.stdouterr() ); if( commit.process.exitCode() != 0 ) { // commit will treat no change as an error. if( output.length < 1 || output[0] != "nothing changed" ) { Util.writeError( "commit failed:" ); logger.infos( 0, output ); throw "commit failed."; } } logger.infos( 2, output ); } catch( e : Dynamic ) { logger.info( 0, Std.string( e ) ); logger.info( 0, "Reverting upstream branch to state before import." ); logger.infos( 2, Mercurial.revert( logger ) ); logger.infos( 3, Mercurial.switchToBranch( Constants.mainBranch(), logger ) ); Util.die( "Could not import tarballs" ); } logger.infos( 3, Mercurial.switchToBranch( Constants.mainBranch(), logger ) ); if( upstream.noMerge ) { logger.info ( 0, "Run hg merge " + Constants.upstreamBranch() + " to pull in new version." ); } else { // Are there any Quilt-managed patches? Then unapply the patches to // avoid getting merge conflicts. if( FileUtil.fileExists( ".pc/applied-patches" ) ) { var output = new List(); output.add( "Unapplying Quilt patches." ); var unpatch = new Process( "quilt", [ "pop", "-a", "-q" ] ); for( line in unpatch.stdouterr() ) output.add( line ); if( unpatch.process.exitCode() != 0 ) { logger.infos( 0, output ); Util.writeError( "Could not unapply patches." ); Util.writeError( "You have to manually unapply patches." ); Util.die ( "Then run hg merge " + Constants.upstreamBranch() + " to pull in new version." ); } logger.infos( 1, output ); } if( FileUtil.fileExists( "debian/changelog" ) ) { createChangeLogEntry( version ); } // Merge the new upstream into the default branch. var merge = Mercurial.merge( Constants.upstreamBranch(), logger ); for( line in merge ) { // Filter out "(branch merge, don't forget to commit)". var dontForget = ~/don.t forget to commit/; if( ! dontForget.match( line ) ) logger.info( 1, line ); } var msg = Constants.importOrig() + " merged upstream version " + version; var commit = Mercurial.commit( msg, logger ); logger.infos( 1, commit ); } } // // Create a new *-1 entry in debian/changelog. // static function createChangeLogEntry( version : String ) { // Chreate a new changelog entry. var fullVersion = version + "-1"; var epoch = DebianChangeLog.parseCurrentChangeLog( logger ).version.epoch; if( epoch != null ) { fullVersion = epoch + ":" + fullVersion; } var dch = Process.runButExitOnError ( "dch", [ "-v", fullVersion, Constants.importOrig() + " imported new upstream version." ], logger ); var format = "debian/source/format"; if( FileUtil.fileExists( format ) ) { var quilt = ~/3\.0 \(quilt\)/; if( quilt.match( neko.io.File.getContent( format ) ) ) { logger.info( 0, "Remember to quilt push -a and sort out any problems." ); logger.info( 0, "After that, commit everything including .pc directory." ); } } } // // Imports the component tarball into a branch named after the component and // commits the changes. Then creates an xdelta file between original // tarball and what can be recreated from the component branch, and commits // the xdelta in the pristine branch. // static function xdeltaComponent( component : Component, upstream : Upstream ) { var name = component.component; var branch = Util.componentBranch( upstream.changeLog.source, name ); Mercurial.switchToBranch( branch, logger ); try { var root = importComponent( component, upstream.changeLog ); if( root == null ) throw "Could not import " + component.tarball; // Recreate a tarball from the component branch contents by // transforming the file names so they are rooted in the component // name. var tarballgz = neko.io.Path.withoutDirectory( component.tarball ); var tarball = tarballgz.substr( 0, tarballgz.lastIndexOf(".") ); var recreated = "recreated-" + tarball; var tarBaseArgs = ["--mode=0", "--owner=0", "--group=0"]; var tarArgs = tarBaseArgs.concat (["-cof", recreated ]); if( name == "." ) { var escape = new EReg ("[%&]", ""); var escapedRoot = escape.replace (root[0], "\\$1"); tarArgs = tarArgs.concat ([ "--no-recursion", "--transform", "s%^.%" + escapedRoot + "%" ]); tarArgs.push( "." ); logger.info( 3, "Starting " + tarArgs.join(" ") ); var pack = new Process( "tar", tarArgs ); if( pack.process.exitCode() != 0 ) { logger.infos( 1, pack.stdouterr() ); throw "Could not recreate " + tarball; } // Now for the rest of it... tarArgs = tarBaseArgs.concat ( [ "-rof", recreated, "--transform", "s%^.%" + escapedRoot + "/&%" ]); for( entry in neko.FileSystem.readDirectory( "." ) ) { if( ! Constants.precious().match( entry ) ) { tarArgs.push( entry ); } } } else { tarArgs.push( root[1] ); } logger.info( 3, "Starting " + tarArgs.join(" ") ); var pack = new Process( "tar", tarArgs ); if( pack.process.exitCode() != 0 ) { logger.infos( 0, pack.stdouterr() ); throw "Packing " + tarball + " failed."; } logger.infos( 3, pack.stdouterr() ); // Create an uncompressed copy of the upstream tarball. if( ! Util.uncompress( component.tarball, tarball ) ) { throw "Could not uncompress " + component.tarball; } // Create an xdelta file between uncompressed upstream tarball and // what was recreated from the component branch. var args = [ "delta", "-p", recreated, tarball, tarball + "." + Constants.xdeltaExtension() ]; logger.info( 3, "Starting xdelta " + args.join(" ") ); var xdelta = new Process( "xdelta", args ); var exit = xdelta.process.exitCode(); if( exit != 1 && exit != 0 ) { logger.infos( 0, xdelta.stdouterr() ); throw "Could not calculate xdelta for pristine tarball."; } logger.infos( 2, xdelta.stdouterr() ); // Create enough information to be able to compress the pristine // tarball so that it becomes identical the the original compressed // tarball. var compression = tarballgz.substr( tarballgz.lastIndexOf(".")+1 ); var pristineInfo = tarball + "." + compression + "." + Constants.pristineExtension(); if( ! Util.preparePristine( component.tarball, pristineInfo ) ) { throw "Could not generate info for pristine tarball."; } // Cleanup and commit component branch. FileUtil.unlink( recreated ); FileUtil.unlink( tarball ); var componentName = name; if( name == "." ) componentName = upstream.changeLog.source; var msg = Constants.importOrig() + " imported " + componentName + " version " + upstream.changeLog.version.upstream; var commit = new Process( "hg", [ "commit", "-m", msg ] ); if( commit.process.exitCode() != 0 ) { logger.infos( 0, commit.stdouterr() ); throw "commit new component failed."; } logger.infos( 2, commit.stdouterr() ); // Remember the revision number so pristinetar can get back to it. var identify = new Process( "hg", ["identify"] ); var out = identify.stdouterr(); if( identify.process.exitCode() != 0 || ! out.hasNext() ) { logger.infos( 0, out ); throw "hg identify failed."; } var revisionRegExp = ~/^([^\s]+)\s/i; if( ! revisionRegExp.match( out.next() ) ) { throw "hg identify did not give a revision."; } var revision = revisionRegExp.matched( 1 ); var revisionInfo = tarball + "." + Constants.revisionExtension(); logger.info( 2, "Storing revision " + revision + " in " + revisionInfo ); var revisionFile = neko.io.File.write( revisionInfo, false ); revisionFile.writeString( revision ); revisionFile.close(); if (name == ".") { logger.info( 2, "Storing root directory name" ); var dir = neko.io.File.write (tarball + "." + Constants.dirExtension(), false); dir.writeString (root[0]); dir.close (); } // Commit the xdelta, pristine-tar, and revision in pristine branch. Mercurial.switchToBranch( Constants.pristineBranch(), logger ); var msg = Constants.importOrig() + " stored xdelta for " + tarball; var commit = Process.runButExitOnError ( "hg", [ "commit", "--addremove", "-m", msg ], logger ); // Tag the upstream branch with the successful import. Mercurial.switchToBranch( Constants.upstreamBranch(), logger ); var tag = Util.upstreamTag( upstream.changeLog, name ); var msg = Constants.importOrig() + " added tag " + tag; var tagger = Mercurial.tag( tag, msg, logger ); logger.infos( 2, tagger ); } catch( e : Dynamic ) { Util.writeError( Std.string( e ) ); logger.info( 0, "Reverting branch " + branch + " to state before import." ); logger.infos( 2, Mercurial.revert( logger ) ); logger.infos( 3, Mercurial.switchToBranch( Constants.mainBranch(), logger ) ); neko.Sys.exit( 1 ); } } // // Imports the component tarball into current branch and prepares for // committing the changes. Returns the names of the original and real // root directories in the component tarball on successful import, or // null if something went wrong (in which case the caller is expected to // revert the changes). // static function importComponent ( component : Component, changeLog : DebianChangeLog ) : Array { var name = component.component; // Delete everything except the Mercurial files. for( entry in neko.FileSystem.readDirectory( "." ) ) { var mercurial = ~/^\.hg$/; if( ! mercurial.match( entry ) ) FileUtil.unlink( entry ); } var root = extractComponent( component ); if( root == null ) return null; // Add and remove files from new component version, but do a lot to // detect renames. var addremove = new Process ( "hg", [ "addremove", "-s", Constants.similarity() ] ); if( addremove.process.exitCode() != 0 ) { Util.writeError( "addremove failed:" ); Lambda.iter( addremove.stdouterr(), logger.error ); return null; } logger.infos( 1, addremove.stdouterr() ); return root; } // // Extracts a component tarball into CWD. The tarball needs to have a // single root directory. The root directory is simply ignored if the // component is ".". Returns the names of the original and real root // directories in the component tarball on successful extraction, or // null if something went wrong. // static function extractComponent( comp : Component ) : Array { var component = comp.component; var tarball = comp.tarball; logger.info( 1, "Unpacking " + tarball ); // Unpack tarballs into a temporary directory. var tmpDir = ",,importorig-" + neko.Sys.time(); try { neko.FileSystem.createDirectory( tmpDir ); } catch( e : Dynamic ) { Util.writeError( "Creating " + tmpDir + ": " + Std.string( e ) ); return null; } if( ! Util.extract( tarball, tmpDir ) ) { FileUtil.unlink( tmpDir ); return null; } // Delete empty directories because they are not tracked by Mercurial. // FIXME/BUG: empty directories may be present in the tarball - omit them and we can not re-create the tarball! // logger.info( 2, "Pruning empty directories from " + tarball ); // FileUtil.prune( tmpDir ); // The tarballs are required (by dpkg-source) to behave nicely and // expand into one single directory, the contents of which are moved to // a directory with the component name, except if the component name is // ".". var entries = neko.FileSystem.readDirectory( tmpDir ); if( entries.length != 1 || ! neko.FileSystem.isDirectory( tmpDir + "/" + entries[0] ) ) { FileUtil.unlink( tmpDir ); Util.writeError ( tarball + " must contain a single root directory." ); return null; } // Move the contents into the right place in the branch. var root = entries[0]; var sourceDir = tmpDir + "/" + root; var target = component; if( target != "." ) { try { neko.FileSystem.createDirectory( target ); } catch( e : Dynamic ) { Util.writeError( "Creating " + target + ": " + Std.string( e ) ); return null; } } logger.info( 2, "Moving contents of " + root + " to " + target ); entries = neko.FileSystem.readDirectory( sourceDir ); for( entry in entries ) { // Ignore files that would interfere with mercurial-buildpackage or // dpkg-source. if( ! Constants.interfere().match( entry ) ) { FileUtil.copy( sourceDir + "/" + entry, target ); } } FileUtil.unlink( tmpDir ); return [root, target]; } // // Returns a structure containing the parsed command-line arguments. // static function parseCommandLine() : Upstream { var usage = "Usage: " + Constants.importOrig() + " [-V|--version]" + " [-v|--verbose] [-n|--no-merge] maintarball [componenttarball...]"; var options = new GetPot( neko.Sys.args() ); Util.maybeReportVersion( options, usage ); // Collect verbosity options. while( options.got( ["--verbose","-v"] ) ) ++logger.verbosity; var noMerge = options.got( ["-n","--no-merge"] ); // Reject other options. Util.exitOnExtraneousOptions( options, usage ); // Get the file name of the tarball(s). var origs = new Array(); var orig = options.unprocessed(); while( orig != null ) { origs.push( orig ); orig = options.unprocessed(); } // There must be at least one tarball. if( origs.length == 0 ) Util.die( usage ); for( tarball in origs ) { if( ! FileUtil.fileExists( tarball ) ) { Util.die( "Tarball " + tarball + " does not exist." ); } } // The names of tarballs must follow Debian conventions of dpkg format // 3.0 (quilt). var ballRegExp = ~/([^\/]+)_(.+)\.orig\.tar\.(bz2|lzma|xz|gz)$/; if( ! ballRegExp.match( origs[0] ) ) { Util.die( "Filename of main tarball must follow the pattern defined by dpkg format 3.0." ); } var packageName = ballRegExp.matched( 1 ); var version = ballRegExp.matched( 2 ); logger.info( 2, "Package " + packageName + " version " + version ); // Only format 3.0 allows multiple tarballs, and format 1.0 only accepts // gzip compression. if( ballRegExp.matched( 3 ) != "gz" ) { logger.info( 2, "Assuming dpkg format 3.0" ); } // Collect tarballs together with their component names. The main // tarball has a component name ".". var components = new Array(); components.push( { component: ".", tarball: origs[0] } ); // Process additional tarball components, if any. var componentRegExp = ~/([^\/]+)_(.*)\.orig-([a-z0-9][-a-z0-9]*)\.tar\.(bz2|lzma|xz|gz)$/i; for( i in 1...origs.length ) { if( ! componentRegExp.match( origs[i] ) ) { Util.die( "Filenames of component tarballs must follow the pattern defined by dpkg format 3.0 (quilt)." ); } if( componentRegExp.matched( 1 ) != packageName ) { Util.die ( origs[0] + " and " + origs[i] + " do not agree on package name." ); } if( componentRegExp.matched( 1 ) != packageName ) { Util.die ( origs[0] + " and " + origs[i] + " do not agree on package name." ); } if( componentRegExp.matched( 2 ) != version ) { Util.die ( origs[0] + " and " + origs[i] + " do not agree on upstream version." ); } components.push ( { component: componentRegExp.matched( 3 ), tarball: origs[i] } ); } // Reject other arguments. Util.exitOnExtraneousArguments( options, usage ); return { components: components, changeLog: new DebianChangeLog( packageName,version ), noMerge: noMerge }; } static var logger : Script; } mercurial-buildpackage-0.10/MercurialPristineTar.man0000644000000000000000000000240211722435531017522 0ustar .TH "{PristineTar}" "1" "December 2009" "{PristineTar} {Version}" "User Commands" .SH NAME {PristineTar} - Recreate pristine source tarballs. .SH SYNOPSIS \fB{PristineTar}\fR [\fIoption\fR] ... [\fIversion\fR] .SH DESCRIPTION Build pristine source tarballs from the Mercurial repository in the current directory. If \fIversion\fR is specified, then tarballs for that version is recreated instead of the most recent from from debian/changelog. .SH OPTIONS .HP \fB\-\-version\fR, \fB\-V\fR .IP Output version and exit. .HP \fB\-\-verbose\fR, \fB\-v\fR .IP Increase verbosity level. Can be used several times. .SH EXAMPLES .HP \fB{PristineTar}\fR 1.2.3 .IP Create pristine ../mypack_1.2.3.orig.tar.{gz,bz2,lzma,xz} and \&../mypack_1.2.3.orig\-component*.tar.{gz,bz2,lzma,xz} if applicable from the repository in the current directory. .SH BUGS Generating tarballs compressed by \fBlzma\fR(1) might not end up being identical to the original because the \fBpristine\-tar\fR(1) suite does not have support for \fBlzma\fR(1). .SH AUTHOR Jens Peter Secher .SH SEE ALSO \fBpristine\-gz\fR(1), \fBpristine\-bz2\fR(1), \fBpristine\-xz\fR(1), \fB{ImportOrig}\fR(1), \fB{ImportDsc}\fR(1), \fB{BuildPackage}\fR(1), \fB{TagVersion}\fR(1), \fB{Port}\fR(1). mercurial-buildpackage-0.10/MakeIter.hx0000644000000000000000000000213611714013023014750 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class MakeIter implements Iter { public function new( iter : Iterator ) { this.iter = iter; } public function iterator() : Iterator { return iter; } public function next() : T { return iter.next(); } public function hasNext() : Bool { return iter.hasNext(); } var iter : Iterator; } mercurial-buildpackage-0.10/GetPot.hx0000644000000000000000000001033011714013023014444 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Inspired by Frank-Rene Schaefer GetPot (see // http://getpot.sourceforge.net/GetPot.html). // class GetPot { // // Call with eg. neko.Sys.args() as argument. // public function new( args : Array ) { arguments = new List>(); // The sequence is filled up with collected arguments. var sequence = new List(); for( arg in args ) { var option = ~/^-/; if( option.match( arg ) ) { // If the collected sequence is not empty when the next argument // is an option, the sequence will have to be flushed and // restarted. if( sequence.length != 0 ) { arguments.add( sequence ); sequence = new List(); } sequence.add( arg ); } else { sequence.add( arg ); } } if( sequence.length != 0 ) { arguments.add( sequence ); } // Make sure next() will return null. nextArg = null; } // // Takes an array of options (eg. ["-C","--check"]) to search for in the // command line, and returns true if any of those options were found. The // first such option found is removed from the command line and the next() // function can then be used to collect following non-option arguments, if // any. // public function got( options : Array ) : Bool { cleanup(); for( sequence in arguments ) { var first = sequence.first(); if( first != null ) { for( option in options ) { if( option == first ) { // Remove the arguments because is has now been processed. sequence.pop(); // Make sure next() will get the next arguments. nextArg = sequence; return true; } } } } return false; } // // Returns the next argument following the last got() option and removes // that argument from the command line. Returns null if there are no more. // public function next() : Null { if( nextArg == null ) return null; return nextArg.pop(); } // // Returns the first option which has not been got() and removes the option // from the command line. Returns null if there are no more options. // public function unknown() : Null { cleanup(); for( sequence in arguments ) { if( sequence.first() != null ) { var option = ~/^-/; if( option.match( sequence.first() ) ) { return sequence.pop(); } } } return null; } // // Returns the first argument which has not been processed yet and removes // it from the command line. Returns null if there are no more unprocessed // arguments. This function should normally only be called after unknown() // has returned null to ensure that all options have been processed. // public function unprocessed() : Null { cleanup(); for( sequence in arguments ) { if( sequence.first() != null ) { return sequence.pop(); } } return null; } // // Each sequence of successive arguments. Every collected option will be // the first element in one of the sequences. Each individual argument is // removed from its sequences when it is processed by got(), next(), // unknown() or unprocessed(). // var arguments : List>; // // Remove all initial empty sequences. // function cleanup() { while( arguments.first() != null && arguments.first().first() == null ) { arguments.pop(); } } // // Points to the sequence of arguments following the last got() option, or // null if no got() has succeeded. // var nextArg : List; } mercurial-buildpackage-0.10/MacroExpand.hx0000644000000000000000000000431311715337306015465 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Process stdin to stdout by expanding macro values defined in Constants. // typedef Substitution = { regExp : String, expander : Void -> String } class MacroExpand { public static function main() { var substitutions : Array = [ { regExp : "{Package}", expander : Constants.packageName }, { regExp : "{BuildPackage}", expander : Constants.buildPackage }, { regExp : "{ImportOrig}", expander : Constants.importOrig }, { regExp : "{ImportDsc}", expander : Constants.importDsc }, { regExp : "{PristineTar}", expander : Constants.pristineTar }, { regExp : "{Port}", expander : Constants.port }, { regExp : "{TagVersion}", expander : Constants.tagVersion }, { regExp : "{Version}", expander : Constants.version }, { regExp : "{UpstreamVersion}", expander : Constants.upstream_version }, { regExp : "{VendorVersion}", expander : Constants.vendor_version }, ]; var input = neko.io.File.stdin(); var stdout = neko.io.File.stdout(); while( true ) { try { stdout.writeString ( Lambda.fold( substitutions, expand, input.readLine() ) ); stdout.writeString( "\n" ); } catch( e : Dynamic ) { // End of file. break; } } neko.Sys.exit( 0 ); } static function expand( substitution : Substitution, input : String ) : String { var regExp = new EReg( substitution.regExp, "g" ); return regExp.replace( input, substitution.expander() ); } } mercurial-buildpackage-0.10/GetPotUnitTest.hx0000644000000000000000000000473511714013023016160 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. class GetPotUnitTest extends haxe.unit.TestCase { public function testNoArgs() { var options = new GetPot( [] ); assertFalse( options.got( ["foo"] ) ); assertEquals( null, options.next() ); assertEquals( null, options.unknown() ); assertEquals( null, options.unprocessed() ); } public function testMultipleArgs() { var options = new GetPot ( ["--move","--in","file1","file2","--out","file3","file4"] ); assertTrue( options.got( ["--move"] ) ); assertEquals( null, options.next() ); assertTrue( options.got( ["--out"] ) ); assertEquals( "file3", options.next() ); assertEquals( "file4", options.next() ); assertEquals( null, options.next() ); assertTrue( options.got( ["--in"] ) ); assertEquals( "file1", options.next() ); assertEquals( "file2", options.next() ); assertEquals( null, options.next() ); assertEquals( null, options.unknown() ); assertEquals( null, options.unprocessed() ); } public function testExtras() { var options = new GetPot ( ["file1","file2","-C","file3","--unknown","file4"] ); assertTrue( options.got( ["--check","-C"] ) ); assertEquals( "--unknown", options.unknown() ); assertEquals( "file1", options.unprocessed() ); assertEquals( "file2", options.unprocessed() ); assertEquals( "file3", options.unprocessed() ); assertEquals( "file4", options.unprocessed() ); assertEquals( null, options.unknown() ); } public function testShortLong() { var options = new GetPot ( ["-null","/var","--0"] ); assertTrue( options.got( ["-null","--0"] ) ); assertTrue( options.got( ["-null","--0"] ) ); var unprocessed = options.unprocessed(); assertEquals( "/var", unprocessed ); assertEquals( null, options.unknown() ); } } mercurial-buildpackage-0.10/Pristine.hx0000644000000000000000000000371511721774262015071 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Used by MercurialPristineTar. Holds all information that is needed to // recreate a pristine tarball from a component branch. // class Pristine { // The Mercurial revision of the component branch from where the tarball can // be regenerated. public var revision (default,null) : String; // The xdelta patch file to make the recreated tarball identical to the // original tarball. public var tarballDelta (default,null) : String; // One of gz, bz2, lzma or xz. public var compression (default,null) : String; // The pristine-{gz,bz2,xz} patch file to compress the patched, recreated // tarball the same way as the original, compressed tarball. public var compressionDelta (default,null) : String; // The name of the top-level directory in the original tarball. // Assumption: that there is one and only one. public var directory (default,null) : String; public function new ( compression : String, compressionDelta : String, tarballDelta : String, revision : String, directory : String ) { this.compression = compression; this.compressionDelta = compressionDelta; this.tarballDelta = tarballDelta; this.revision = revision; this.directory = directory; } } mercurial-buildpackage-0.10/MercurialPort.man0000644000000000000000000000202611722435511016202 0ustar .TH "{Port}" "1" "December 2009" "{Port} {Version}" "User Commands" .SH NAME {Port} - Incorporate an already released version of a package source into a specific porting branch. .SH SYNOPSIS \fB{Port}\fR [\fIoption\fR] \fIbranch\fR .SH DESCRIPTION Switch to the specified branch and merge with the default branch. The specified branch is created if necessary. .SH OPTIONS .HP \fB\-\-version\fR, \fB\-V\fR .IP Output version and exit. .HP \fB\-\-verbose\fR, \fB\-v\fR .IP Increase verbosity level. Can be used several times. .HP \fB\-\-package\-version\fR \fIversion\fR, \fB\-p\fR \fIversion\fR .IP Merge \fIversion\fR into \fIbranch\fR instead of using the most recent version from \fBdebian/changelog\fR. .SH EXAMPLES .HP \fB{Port}\fR \fB\-p\fR 3.2\-1 lenny .IP Merge version 3.2\-1 of the package in the current directory into the branch lenny. .SH AUTHOR Jens Peter Secher .SH SEE ALSO \fB{ImportOrig}\fR(1), \fB{ImportDsc}\fR(1), \fB{BuildPackage}\fR(1), \fB{TagVersion}\fR(1), \fB{PristineTar}\fR(1). mercurial-buildpackage-0.10/Process.hx0000644000000000000000000000536711721774357014724 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // Shell process container and utilities. class Process { public static function runButExitOnError ( command : String, args : Array, logger : ILog, /// By default, the output is returned in an iterator. ? level : Int = 0xFFFF, /// By default, only the exit code 0 is accepted. ? acceptableExitCodes : Array, /// By default, CWD is not changed. ? workingDirectory : String ) : Iter { // Change working directory if necessary. var cwd : String = null; if( workingDirectory != null ) { cwd = neko.Sys.getCwd(); neko.Sys.setCwd( workingDirectory ); } var p = new Process( command, args ); var context = new List(); for( line in p.stdouterr() ) { // Put all output in the log. logger.log( line ); // If the logger's verbosity is at least as high as the info level, // then also display the line. if( logger.verbosity >= level ) { logger.info( level, line ); } // Maintain the context. else { context.add( line ); } } // Change working directory back if necessary. if( cwd != null ) { neko.Sys.setCwd( cwd ); } // Check process exit code. if( acceptableExitCodes == null ) acceptableExitCodes = [0]; if( ! Lambda.has( acceptableExitCodes, p.process.exitCode() ) ) { // Process failed, abort with context. Lambda.iter( context, function(line) logger.info( 0, line ) ); logger.error( p.command + " failed." ); neko.Sys.exit( 1 ); } // Process succeeded. return new MakeIter( context.iterator() ); } public var process (default,null) : neko.io.Process; public function new( command: String, args: Array ) { this.command = command + " " + args.join( " " ); process = new neko.io.Process( command, args ); } // // Combine stdout and stderr into one iterator. // public function stdouterr() : Iter { return new ProcessTwoStreamIterator( process.stdout, process.stderr, process ); } var command (default,null) : String; } mercurial-buildpackage-0.10/DebianChangeLog.hx0000644000000000000000000000373411721774357016234 0ustar // Copyright (c) 2010, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // Structure for holding the relevant parts of a Debian package's changelog, see // Debian Policy section 4.4. // TODO: Rename to someting else because it is used to hold eg, parsed hg tags. class DebianChangeLog { public var source (default,null) : String; public var version (default,null) : DebianPackageVersion; public function new( source : String, version : String ) { this.source = source; this.version = new DebianPackageVersion( version ); } // Extract package information from the changelog file in the current // directory. Aborts the program if a changelog cannot be found. public static function parseCurrentChangeLog( logger : ILog ) : DebianChangeLog { // Get the changelog. var changeLog = Process.runButExitOnError( "dpkg-parsechangelog", [], logger ); // Parse the changelog. var version = ""; var source = ""; var versionRegExp = ~/^Version:[ \t]+(.+)$/; var sourceRegExp = ~/^Source:[ \t]+(.+)$/; for( line in changeLog ) { if( versionRegExp.match( line ) ) { version = versionRegExp.matched(1); } else if( sourceRegExp.match( line ) ) { source = sourceRegExp.matched(1); } } return new DebianChangeLog( source, version ); } } mercurial-buildpackage-0.10/MercurialTagVersion.man0000644000000000000000000000174311722435550017347 0ustar .TH "{TagVersion}" "1" "December 2009" "{TagVersion} {Version}" "User Commands" .SH NAME {TagVersion} - Tag the Mercurial package source with the most recent version from the changelog. .SH SYNOPSIS \fB{TagVersion}\fR [\fIoption\fR] ... .SH DESCRIPTION Extract the most recent version from \fBdebian/changelog\fR and tag the Mercurial repository with that version. .SH OPTIONS .HP \fB\-\-version\fR, \fB\-V\fR .IP Output version and exit. .HP \fB\-\-verbose\fR, \fB\-v\fR .IP Increase verbosity level. Can be used several times. .HP \fB\-\-ignore\-uncommited\fR, \fB\-i\fR .IP Do not check for uncommited changes in the Mercurial repository. .HP \fB\-\-force\fR, \fB\-f\fR .IP Overwrite existing tag, if any. .SH AUTHOR Jens Peter Secher .SH THANKS The ideas for this package originates from John Goerzen's \fBhg\-buildpackage\fR. .SH SEE ALSO \fB{ImportOrig}\fR(1), \fB{ImportDsc}\fR(1), \fB{PristineTar}\fR(1), \fB{BuildPackage}\fR(1), \fB{Port}\fR(1). mercurial-buildpackage-0.10/MercurialPort.hx0000644000000000000000000000646411721774357016075 0ustar // Copyright (c) 2009, Jens Peter Secher // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. typedef Port = { var branch : String; var version : String; } class MercurialPort { public static function main() { logger = new Script(); var port : Port = parseCommandLine(); // Extract package information from the changelog file. Mercurial.switchToBranch( Constants.mainBranch(), logger ); var changeLog = DebianChangeLog.parseCurrentChangeLog( logger ); // Override version if specified on the command line. if( port.version != null ) { changeLog = new DebianChangeLog( changeLog.source, port.version ); } logger.info( 1, "Merging " + changeLog.version + " into " + port.branch ); // Search for a tag matching the version. var tag = Util.fullTag( changeLog ); if( ! Mercurial.hasTag( tag, logger ) ) { Util.die ( "No tag " + tag + " exists for version " + changeLog.version ); } // Merge the specified version into the port branch. Mercurial.switchToBranch( port.branch, logger ); var merge = Mercurial.merge( tag, logger ); for( line in merge ) { // Filter out "(branch merge, don't forget to commit)". var dontForget = ~/don.t forget to commit/; if( ! dontForget.match( line ) ) logger.info( 1, line ); } var msg = Constants.port() + " merged version " + changeLog.version + " into " + port.branch; var commit = Mercurial.commit( msg, logger ); for( line in commit ) logger.info( 1, line ); logger.info( 0, "You are now in branch " + port.branch ); logger.info( 0, "Use hg up default to get back to main development branch." ); } // // Returns the branch and merge instructions from the parsed command-line // arguments. // static function parseCommandLine() : Port { var usage = "Usage: " + Constants.port() + " [-V|--version]" + " [-v|--verbose] [-p|--package-version packageversion] branch"; var options = new GetPot( neko.Sys.args() ); Util.maybeReportVersion( options, usage ); // Collect verbosity options. while( options.got( ["--verbose","-v"] ) ) ++logger.verbosity; var version : String = null; if( options.got( ["-p","--package-version"] ) ) { version = options.next(); if( version == null ) { Util.die( "No package version specified." ); } } // Reject other options. Util.exitOnExtraneousOptions( options, usage ); // Get the branch name. var branch = options.unprocessed(); if( branch == null ) Util.die( usage ); // Reject other arguments. Util.exitOnExtraneousArguments( options, usage ); Mercurial.exitIfUncommittedChanges( logger ); return { branch: branch, version: version }; } static var logger : Script; }