diff options
author | Miklos Vajna <vmiklos@frugalware.org> | 2009-07-25 13:12:15 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@frugalware.org> | 2009-07-25 13:12:15 +0200 |
commit | 122e02c3d7a3c6196f54204174000b6089640899 (patch) | |
tree | d04730fa6a6f41f7795fa092f71290d30f708ad9 /exporters | |
parent | 5b935b4bb76687c93ecf5c3afc2c3e38256a167e (diff) | |
parent | dd8b6a4e38675f5445557339b96e1afd718f74bb (diff) | |
download | bzr-fastimport-122e02c3d7a3c6196f54204174000b6089640899.tar.gz |
Merge darcs-fast-export
Diffstat (limited to 'exporters')
50 files changed, 2632 insertions, 0 deletions
diff --git a/exporters/darcs/.gitignore b/exporters/darcs/.gitignore new file mode 100644 index 0000000..d26377c --- /dev/null +++ b/exporters/darcs/.gitignore @@ -0,0 +1,3 @@ +Changelog +HEADER.html +.htaccess diff --git a/exporters/darcs/Makefile b/exporters/darcs/Makefile new file mode 100644 index 0000000..0c81c68 --- /dev/null +++ b/exporters/darcs/Makefile @@ -0,0 +1,55 @@ +VERSION = 0.9 +DATE := $(shell date +%Y-%m-%d) + +INSTALL = /usr/bin/install -c +DESTDIR = +prefix = /usr +bindir = $(prefix)/bin +mandir = $(prefix)/share/man/man1 + +MAN_TXT = $(wildcard *.txt) +MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) +MAN=$(patsubst %.txt,%.1,$(MAN_TXT)) + +PROGRAMS = darcs-fast-export darcs-fast-import d2x x2d git-darcs + +all: man + +install: all + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) -d $(DESTDIR)$(mandir) + $(INSTALL) -m755 $(PROGRAMS) $(DESTDIR)$(bindir) + $(INSTALL) -m644 *.1 $(DESTDIR)$(mandir) + +doc: HEADER.html Changelog html + +HEADER.html: README Makefile + asciidoc -a toc -a numbered -a sectids -o HEADER.html README + +Changelog: .git/refs/heads/master + git log >Changelog + +%.html: %.txt + asciidoc $^ + +%.1: %.txt asciidoc.conf + a2x --asciidoc-opts="-f asciidoc.conf" \ + -a dfe_version=$(VERSION) -a dfe_date=$(DATE) -f manpage $< + +man: $(MAN) + +html: $(MAN_HTML) + +dist: + git archive --format=tar --prefix=darcs-fast-export-$(VERSION)/ $(VERSION) > darcs-fast-export-$(VERSION).tar + mkdir -p darcs-fast-export-$(VERSION) + git log > darcs-fast-export-$(VERSION)/Changelog + tar rf darcs-fast-export-$(VERSION).tar darcs-fast-export-$(VERSION)/Changelog + rm -rf darcs-fast-export-$(VERSION) + gzip -f -9 darcs-fast-export-$(VERSION).tar + +release: + git tag -l |grep -q $(VERSION) || dg tag $(VERSION) + $(MAKE) dist + gpg --comment "See http://vmiklos.hu/gpg/ for info" \ + -ba darcs-fast-export-$(VERSION).tar.gz diff --git a/exporters/darcs/NEWS b/exporters/darcs/NEWS new file mode 100644 index 0000000..1a0daa5 --- /dev/null +++ b/exporters/darcs/NEWS @@ -0,0 +1,26 @@ +VERSION DESCRIPTION +----------------------------------------------------------------------------- +0.9 - fix handling of accents in tag names + - warning fixes for Python-2.6 + - git-darcs: the add subcommand can now remember d-f-e + options + - git-darcs: new list, find-darcs and find-git subcommands +0.8 - revert the "not exporting unchanged files multiple + times" optimization, it causes corrupted results in some + cases. +0.7 - new darcs-fast-export option: --progress + - massive speedup in darcs-fast-export due to not + exporting unchanged files multiple times and reading + patches directly +0.6 - add a new darcs-fast-import script, allowing two-way sync + - new darcs-fast-export option: --git-branch + - add a new git-darcs script, making two-way sync easy +0.5 - new --help, --encoding, --authors-file, --working and + --logfile options + - add "hashed" support (see darcs init -h) + - add incremental conversion support for darcs1 as well + - add d2x wrapper script +0.4 - add incremental conversion support +0.3 - add darcs2 support +0.2 - add bzr and hg support +0.1 - initial short and fast version, supporting darcs1->git diff --git a/exporters/darcs/README b/exporters/darcs/README new file mode 100644 index 0000000..4b13e3b --- /dev/null +++ b/exporters/darcs/README @@ -0,0 +1,192 @@ += darcs backend for fast data importers +Miklos Vajna <vmiklos-at-frugalware-dot-org> + +== Purpose and Features + +darcs-fast-export is a tool to dump a http://darcs.net/[darcs] +repository in a format understood by "fast-importers" such as +http://git.or.cz/[git] +http://www.kernel.org/pub/software/scm/git/docs/git-fast-import.html[fast-import]. +It exhibits the following _features:_ + +Fast:: + darcs-fast-export provides a fast darcs backend for fast-import. + See link:t/bench-results/[here] for exact details. + +Correct:: + darcs-fast-export produces correct results in any extreme cases. + It has been tested with a collection of large darcs repos (called + http://code.haskell.org/darcs/big-zoo/[big-zoo]). And several testcases + under the `t/` directory. + +Independent:: + Ideally it should work with any fast importer, but actually it has been + tested with git fast-import, bzr fast-import and hg fastimport. (These + are the three fast-import implementations available ATM.) + + + hg fastimport needs three patches. While they are not in the upstream, + you can get it from my repository using ++ +---- +$ hg clone static-http://frugalware.org/~vmiklos/hg/hg-fastimport +---- + +Formats:: + It supports the 'darcs-2', 'hashed', and 'old-fashioned-inventory' darcs + repository formats. + +Incremental conversions:: + It supports the usual `--export-marks` / `--import-marks` switches to + allow incremental conversion. + +Wrapper scripts:: + A wrapper script called `d2x` is available if you find typing + `--export-marks` / `--import-marks` all the time boring. A similar one + is also provided for the other direction, called `x2d`. Finally, if you + want to work on darcs repos with git, you can use the `git-darcs` + wrapper. + +Author mappings:: + Supports `--authors-file` option like Git's SVN adaptor, for DARCS + repositories that originated in CVS or SVN. + +Import script:: + The pair of `darcs-fast-export`, `darcs-fast-import` is also + included in this repo. It has been tested with the fast-expoters of Git, + Hg, Bzr and - of course - Darcs itself. + +Two-way sync:: + Using `darcs-fast-export` / `darcs-fast-import`, it is possible to + convert a darcs repo to an other VCS, work there, then convert your work + back to Darcs (or vica versa). This has been tested with "darcs -> git; + hack hack; git -> darcs". + +== Usage + +See the manpages: + +* link:darcs-fast-export.html[darcs-fast-export] +* link:darcs-fast-import.html[darcs-fast-import] +* link:d2x.html[d2x] +* link:x2d.html[x2d] +* link:git-darcs.html[git-darcs] + +=== Example + +Assuming that `test/` is a darcs repo, you could do this: +---- +$ mkdir test.git +$ cd test.git +$ git --bare init +$ cd .. +$ darcs-fast-export test |(cd test.git; git fast-import) +---- + +For more examples (especially for bzr and hg), see the `t/` directory. + +== Download + +Using git: +---- +$ git clone git://vmiklos.hu/darcs-fast-export +---- + +== Status + +In general, darcs-fast-export should work fine. darcs-fast-import has +known problems with tags - other than that it should be okay. git-darcs +should work properly as long as you are not paying too much attention to +the imported tags (newly created tags won't be pushed back). + +darcs-fast-export has been tested with the following versions: + +Darcs version (see http://bugs.darcs.net/issue844[this bug] on why do +you need such a new version): +---- +$ darcs --version +2.2.0 (release) +---- + +Git version: +---- +$ git --version +git version 1.6.0.2 +---- + +Bzr versions: +---- +$ bzr version +Bazaar (bzr) 1.12 +$ (cd ~/bzr/fastimport; bzr log --limit 1|grep revno) +revno: 181 +---- + +Yes, you need the fastiport plugin from BZR, the last hg release series +supported by fastimport-0.6 is hg-1.0.x. + +Mercurial (Hg) version: +---- +$ hg version +Mercurial Distributed SCM (version 1.2.1) +---- + +Strictly speaking this document is a wrong place to talk about enabling +hg plugins. However... + +---- +$ cat ~/.hgrc +[extensions] +hgext.fastimport= +---- + +and once you installed the plugin correctly, you should have something like: + +---- +$ ls /usr/lib/python*/site-packages/hgext/fastimport/__init__.py +/usr/lib/python2.5/site-packages/hgext/fastimport/__init__.py +---- + +== Additional resources + +You can reach the Changelog link:Changelog[here], and a gitweb interface +http://vmiklos.hu/gitweb/?p=darcs-fast-export.git[here]. + +The fast-import stream format documentation is +http://git.kernel.org/?p=git/git.git;a=blob;f=fast-import.c;hb=HEAD[here] +if you're interested. + +== Alternatives + +- http://repo.or.cz/w/darcs2git.git[darcs2git] tries to find conflict + resolutions (to map them to merge commits), but it's rather slow + because of this. It does not support the darcs2 format and/or + incremental conversions, either. darcs-fast-export may support mapping + to merge commits later, but not before + http://bugs.darcs.net/issue1261[this issue] is addressed. + +- http://progetti.arstecnica.it/tailor[tailor] is an any2any VCS + converter, but it produces corrupted results when converting the + big-zoo - see http://progetti.arstecnica.it/tailor/ticket/171[this + ticket]. + +- http://git.sanityinc.com/?p=darcs-to-git.git[darcs-to-git] is similar + to darcs2git, but it fails for the testcases found in the testsuite of + darcs-fast-export. + +- http://github.com/freshtonic/undarcs/tree/master[undarcs] claims to be + fast, but its own README says it produces incorrect results. When I + tried, it did not handle the darcs2 format, binary files and incremental + support. + +== Thanks + +- Jason Dagit for helping me with darcs2 issues +- Shawn O. Pearce and Johannes Schindelin for writing `git-fast-import` + / `git-fast-export` +- Ian Clatworthy for writing bzr fast-import +- Paul Crowley for writing hg fast-import +- Matthias Andree for assorted improvements, among them the --help, + --encoding and --authors-file features (using Python's optparse), support + for hashed repositories, `_darcs/format` interpretation, and mangling + whitespace in tags to cope with repos imported into DARCS from CVS. +- Pieter de Bie for writing git-bzr, which was the base of git-darcs diff --git a/exporters/darcs/TODO b/exporters/darcs/TODO new file mode 100644 index 0000000..2f199d1 --- /dev/null +++ b/exporters/darcs/TODO @@ -0,0 +1,6 @@ +more intelligent tests, such as detect if the hg fastimport extension is +not enabled, etc. + +parse the patches manually so we can avoid re-adding existing files manually. + +avoid darcs apply. diff --git a/exporters/darcs/asciidoc.conf b/exporters/darcs/asciidoc.conf new file mode 100644 index 0000000..cb31717 --- /dev/null +++ b/exporters/darcs/asciidoc.conf @@ -0,0 +1,21 @@ +ifdef::doctype-manpage[] +ifdef::backend-docbook[] +[header] +template::[header-declarations] +<refentry> + <refentryinfo> + <date>{dfe_date}</date> + </refentryinfo> + <refmeta> + <refentrytitle>{mantitle}</refentrytitle> + <manvolnum>{manvolnum}</manvolnum> + <refmiscinfo class="source">darcs-fast-export</refmiscinfo> + <refmiscinfo class="version">{dfe_version}</refmiscinfo> + <refmiscinfo class="manual">darcs-fast-export manual</refmiscinfo> + </refmeta> + <refnamediv> + <refname>{manname}</refname> + <refpurpose>{manpurpose}</refpurpose> + </refnamediv> +endif::backend-docbook[] +endif::doctype-manpage[] diff --git a/exporters/darcs/d2x b/exporters/darcs/d2x new file mode 100755 index 0000000..79e18a3 --- /dev/null +++ b/exporters/darcs/d2x @@ -0,0 +1,114 @@ +#!/bin/sh +# +# d2x - convert darcs repos to git, bzr or hg using fast-import +# +# Copyright (c) 2008 by Miklos Vajna <vmiklos@frugalware.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +usage() +{ + echo "Usage: d2x -f format darcsrepo" +} + +die() +{ + echo "$@" + usage + exit 1 +} + +check_up_to_date() +{ + upstreamnum=$(cd $origin; darcs show repo|grep 'Num Patches'|sed 's/.*: //') + if [ "$upstreamnum" = "$(eval $*)" ]; then + echo "No remote changes to pull!" + exit 0 + fi +} + +case $1 in + -h|--help) + usage + exit 0 + ;; + -f) + format="$2" + shift 2 + ;; +esac + +[ -n "$format" ] || die "Target format is not given!" + +case $format in + git|bzr|hg) + ;; + *) + die "The requested target format is not yet supported!" + ;; +esac + +origin="$1" +shift 1 + +[ -d "$origin" ] || die "Source repo does not exist!" + +# convert to abspath +cd $origin +origin=$(pwd) + +dmark="$origin.$format/darcs/dfe-marks" +fmark="$origin.$format/darcs/ffi-marks" + +mkdir -p $origin.$format/darcs +cd $origin.$format + +common_opts="--working $origin.$format/darcs/repo --logfile $origin.$format/darcs/log $origin" +if [ ! -f $dmark ]; then + case $format in + git) + git --bare init + darcs-fast-export $* --export-marks=$dmark $common_opts | \ + git fast-import --export-marks=$fmark + ;; + bzr) + bzr init-repo . + darcs-fast-export $* --export-marks=$dmark $common_opts | \ + bzr fast-import --export-marks=$fmark - + ;; + hg) + hg init + darcs-fast-export $* $origin | \ + hg fastimport /dev/stdin + esac +else + case $format in + git) + check_up_to_date "git rev-list HEAD |wc -l" + darcs-fast-export $* --export-marks=$dmark --import-marks=$dmark $common_opts | \ + git fast-import --export-marks=$fmark --import-marks=$fmark + ;; + bzr) + check_up_to_date "cd master; bzr revno" + darcs-fast-export $* --export-marks=$dmark --import-marks=$dmark $common_opts | \ + bzr fast-import --export-marks=$fmark --import-marks=$fmark - + ;; + hg) + die "Incremental conversion to hg is not yet supported by hg fastimport." + ;; + esac +fi diff --git a/exporters/darcs/d2x.txt b/exporters/darcs/d2x.txt new file mode 100644 index 0000000..41732fd --- /dev/null +++ b/exporters/darcs/d2x.txt @@ -0,0 +1,27 @@ += d2x(1) + +== NAME + +d2x - convert darcs repos to git, bzr or hg using fast-import + +== SYNOPSIS + +d2x -f <format> <darcsrepo> [<darcs-fast-export options>] + +== DESCRIPTION + +d2x is a wrapper script that just automates doing an initial or +continuing an incremental conversion. All it does is initializing the +target repo, starting darcs-fast-export and the relevant importer with +the proper switches and pipe the exporter's output to the importer's +standard input. + +== OPTIONS + +--help:: + Display usage. + +-f <format>:: + Specify the format of the target repo. Currently supported targets are + git, bzr and hg. Incremental conversion is supported in case of git and + bzr. diff --git a/exporters/darcs/darcs-fast-export b/exporters/darcs/darcs-fast-export new file mode 100755 index 0000000..7fa9663 --- /dev/null +++ b/exporters/darcs/darcs-fast-export @@ -0,0 +1,337 @@ +#!/usr/bin/env python + +""" + + darcs-fast-export - darcs backend for fast data importers + + Copyright (c) 2008 Miklos Vajna <vmiklos@frugalware.org> + Copyright (c) 2008 Matthias Andree <matthias.andree@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +""" + +import xml.dom.minidom +import xml.parsers.expat +import os +import sys +import gzip +import time +import shutil +import subprocess +import optparse +import re + +sys = reload(sys) +sys.setdefaultencoding("utf-8") + +def __get_zone(): + now = time.localtime() + if time.daylight and now[-1]: + offset = time.altzone + else: + offset = time.timezone + hours, minutes = divmod(abs(offset), 3600) + if offset > 0: + sign = "-" + else: + sign = "+" + return sign, hours, minutes + +def get_zone_str(): + sign, hours, minutes = __get_zone() + return "%s%02d%02d" % (sign, hours, minutes // 60) + +def get_zone_int(): + sign, hours, minutes = __get_zone() + ret = hours*3600+minutes*60 + if sign == "-": + ret *= -1 + return ret + +def get_patchname(patch): + ret = [] + s = "" + if patch.attributes['inverted'].value == 'True': + s = "UNDO: " + ret.append(s + patch.getElementsByTagName("name")[0].childNodes[0].data) + lines = patch.getElementsByTagName("comment") + if lines: + for i in lines[0].childNodes[0].data.split('\n'): + if not i.startswith("Ignore-this: "): + ret.append(i) + return "\n".join(ret).encode('utf-8') + +def get_author(patch): + """darcs allows any freeform string, but fast-import has a more + strict format, so fix up broken author names here.""" + + author = patch.attributes['author'].value + if author in authormap: + author = authormap[author] + if not len(author): + author = "darcs-fast-export <darcs-fast-export>" + # add missing name + elif not ">" in author: + author = "%s <%s>" % (author.split('@')[0], author) + # avoid double quoting + elif author[0] == '"' and author[-1] == '"': + author = author[1:-1] + # name after email + elif author[-1] != '>': + author = author[author.index('>')+2:] + ' ' + author[:author.index('>')+1] + return author.encode('utf-8') + +def get_date(patch): + try: + date = time.strptime(patch, "%Y%m%d%H%M%S") + except ValueError: + date = time.strptime(patch[:19] + patch[-5:], '%a %b %d %H:%M:%S %Y') + return int(time.mktime(date)) + get_zone_int() + +def progress(s): + print "progress [%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), s) + sys.stdout.flush() + +def log(s): + logsock.write("[%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), s)) + logsock.flush() + +hashes = [] +def parse_inventory(sock=None): + prev = None + nextprev = False + buf = [] + if not sock: + sock = open(os.path.join("_darcs", "hashed_inventory")) + for i in sock.readlines(): + if i.startswith("hash"): + buf.insert(0, i[6:-1]) + if i.startswith("Starting with inventory:"): + nextprev = True + elif nextprev: + prev = i[:-1] + nextprev = False + sock.close() + for i in buf: + hashes.insert(0, i) + if prev: + sock = gzip.open(os.path.join("_darcs", "inventories", prev)) + parse_inventory(sock) + +# Option Parser +usage="%prog [options] darcsrepo" +opp = optparse.OptionParser(usage=usage) +opp.add_option("--import-marks", metavar="IFILE", + help="read state for incremental imports from IFILE") +opp.add_option("--export-marks", metavar="OFILE", + help="write state for incremental imports from OFILE") +opp.add_option("--encoding", + help="encoding of log [default: %default], if unspecified and input isn't utf-8, guess") +opp.add_option("--authors-file", metavar="F", + help="read author transformations in old=new format from F") +opp.add_option("--working", metavar="W", + help="working directory which is removed at the end of non-incremental conversions") +opp.add_option("--logfile", metavar="L", + help="log file which contains the output of external programs invoked during the conversion") +opp.add_option("--git-branch", metavar="B", + help="git branch [default: refs/heads/master]") +opp.add_option("--progress", metavar="P", + help="insert progress statements after every n commit [default: 100]") +(options, args) = opp.parse_args() +if len(args) < 1: + opp.error("darcsrepo required") + +export_marks = [] +import_marks = [] +if options.import_marks: + sock = open(options.import_marks) + for i in sock.readlines(): + line = i.strip() + if not len(line): + continue + import_marks.append(line.split(' ')[1]) + export_marks.append(line) + sock.close() + +# read author mapping file in gitauthors format, +# i. e. in=out (one per # line) +authormap = {} +if options.authors_file: + sock = open(options.authors_file) + authormap = dict([i.strip().split('=',1) for i in sock]) + sock.close() + +origin = os.path.abspath(args[0]) +if options.working: + working = os.path.abspath(options.working) +else: + working = "%s.darcs" % origin +patchfile = "%s.patch" % origin +if options.logfile: + logfile = os.path.abspath(options.logfile) +else: + logfile = "%s.log" % origin +logsock = open(logfile, "a") +if options.git_branch: + git_branch = options.git_branch +else: + git_branch = "refs/heads/master" + +if options.progress: + prognum = int(options.progress) +else: + prognum = 100 + +progress("getting list of patches") +if not len(import_marks): + sock = os.popen("darcs changes --xml --reverse --repo %s" % origin) +else: + sock = os.popen("darcs changes --xml --reverse --repo %s --from-match 'hash %s'" % (origin, import_marks[-1])) +buf = sock.read() +sock.close() +# this is hackish. we need to escape some bad chars, otherwise the xml +# will not be valid +buf = buf.replace('\x1b', '^[') +if options.encoding: + xmldoc = xml.dom.minidom.parseString(unicode(buf, options.encoding).encode('utf-8')) +else: + try: + xmldoc = xml.dom.minidom.parseString(buf) + except xml.parsers.expat.ExpatError: + import chardet + progress("encoding is not utf8, guessing charset") + encoding = chardet.detect(buf)['encoding'] + progress("detected encoding is %s" % encoding) + xmldoc = xml.dom.minidom.parseString(unicode(buf, encoding).encode('utf-8')) +sys.stdout.flush() + +darcs2 = False +oldfashionedpatch = True +cwd = os.getcwd() +if os.path.exists(os.path.join(origin, "_darcs", "format")): + sock = open(os.path.join(origin, "_darcs", "format")) + format = [x.strip() for x in sock] + sock.close() + darcs2 = 'darcs-2' in format + oldfashionedpatch = not 'hashed' in format +if not oldfashionedpatch: + progress("parsing the inventory") + os.chdir(origin) + parse_inventory() +if not options.import_marks or not os.path.exists(working): + # init the tmp darcs repo + os.mkdir(working) + os.chdir(working) + if darcs2: + os.system("darcs init --darcs-2") + else: + os.system("darcs init --old-fashioned-inventory") +else: + os.chdir(working) +if options.import_marks: + sock = os.popen("darcs pull -a --match 'hash %s' %s" % (import_marks[-1], origin)) + log("Building/updating working directory:\n%s" % sock.read()) + sock.close() + +# this is the number of the NEXT patch +count = 1 +patches = xmldoc.getElementsByTagName('patch') +if len(import_marks): + patches = patches[1:] + count = len(import_marks) + 1 +if len(export_marks): + # this is the mark number of the NEXT patch + markcount = int(export_marks[-1].split(' ')[0][1:]) + 1 +else: + markcount = count +# this may be huge and we need it many times +patchnum = len(patches) + +if not len(import_marks): + progress("starting export, repo has %d patches" % patchnum) +else: + progress("continuing export, %d patches to convert" % patchnum) +paths = [] +for i in patches: + # apply the patch + hash = i.attributes['hash'].value + buf = ["\nNew patches:\n"] + if oldfashionedpatch: + sock = gzip.open(os.path.join(origin, "_darcs", "patches", hash)) + else: + sock = gzip.open(os.path.join(origin, "_darcs", "patches", hashes[count-1])) + buf.append(sock.read()) + sock.close() + sock = os.popen("darcs changes --context") + buf.append(sock.read()) + sock.close() + sock = subprocess.Popen(["darcs", "apply", "--allow-conflicts"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) + sock.stdin.write("".join(buf)) + sock.stdin.close() + log("Applying %s:\n%s" % (hash, sock.stdout.read())) + sock.stdout.close() + message = get_patchname(i) + # export the commit + print "commit %s" % git_branch + print "mark :%s" % markcount + if options.export_marks: + export_marks.append(":%s %s" % (markcount, hash)) + date = get_date(i.attributes['date'].value) + print "committer %s %s %s" % (get_author(i), date, get_zone_str()) + print "data %d\n%s" % (len(message), message) + if markcount > 1: + print "from :%s" % (markcount-1) + # export the files + for j in paths: + print "D %s" % j + paths = [] + for (root, dirs, files) in os.walk ("."): + for f in files: + j = os.path.normpath(os.path.join(root, f)) + if j.startswith("_darcs") or "-darcs-backup" in j: + continue + paths.append(j) + sock = open(j) + buf = sock.read() + sock.close() + # darcs does not track the executable bit :/ + print "M 644 inline %s" % j + print "data %s\n%s" % (len(buf), buf) + if message[:4] == "TAG ": + tag = re.sub('[^\xe9-\xf8\w.\-]+', '_', message[4:].strip().split('\n')[0]).strip('_') + print "tag %s" % tag + print "from :%s" % markcount + print "tagger %s %s %s" % (get_author(i), date, get_zone_str()) + print "data %d\n%s" % (len(message), message) + if count % prognum == 0: + progress("%d/%d patches" % (count, patchnum)) + count += 1 + markcount += 1 + +os.chdir(cwd) + +if not options.export_marks: + shutil.rmtree(working) +logsock.close() + +if options.export_marks: + progress("writing export marks") + sock = open(options.export_marks, 'w') + sock.write("\n".join(export_marks)) + sock.write("\n") + sock.close() + +progress("finished") diff --git a/exporters/darcs/darcs-fast-export.txt b/exporters/darcs/darcs-fast-export.txt new file mode 100644 index 0000000..f0dabf9 --- /dev/null +++ b/exporters/darcs/darcs-fast-export.txt @@ -0,0 +1,61 @@ += darcs-fast-export(1) + +== NAME + +darcs-fast-export - darcs frontend to git fast-import + +== SYNOPSIS + +darcs-fast-export [<options>] <darcsrepo> + +== DESCRIPTION + +darcs-fast-export expects one argument, the path to the source darcs +repository. It will print the git fast-import format on standard output +(stdout). + +The script can produce the fast-import stream format from the darcs +repository. It supports incremental conversion as well, via the +--import-marks / --export-marks switches. + +== OPTIONS + +-h, --help:: + Display usage. + +--import-marks:: + Import marks from a given file. This is read at the beginning of the + conversion at once. Use it if you want to continue an incremental + conversion. + +--export-marks:: + Export marks to a given file at the end of the conversion. It can be the + same as the one for --import-marks as it is written only once at the + end. Use it if you want to be able to incrementally update the target + repository later. + +--encoding:: + The encoding of the author names and commit messages in the repository. + The default is utf-8. If it is not the default, it will be guessed. + Given that it takes some time, you can explicitly specify it as an + option to make the conversion faster. Content in the output will encoded + as utf-8 and will be written that way to the target repository, unless + the importer re-encodes it again to some other character set. + +--working:: + The conversion is done by applying the patches one by one and recording + the state of the working directory. You can specify the path of this + directory using this option. + +--logfile:: + The output of external commands are redirected to a log file. You can + specify the path of that file with this parameter. + +--git-branch:: + There is only one branch in one darcs repository, but the fast-import + stream format allows multiple branches, thus the exporter has to name + darcs's branch. The default value is 'refs/heads/master'. + +--progress:: + Insert progress statements after every <n> patches, to be shown by the + fast importer during import. diff --git a/exporters/darcs/darcs-fast-import b/exporters/darcs/darcs-fast-import new file mode 100755 index 0000000..2955164 --- /dev/null +++ b/exporters/darcs/darcs-fast-import @@ -0,0 +1,310 @@ +#!/usr/bin/env python + +""" + + darcs-fast-export - darcs backend for fast data exporters + + Copyright (c) 2008 Miklos Vajna <vmiklos@frugalware.org> + Copyright (c) 2008 Matthias Andree <matthias.andree@gmx.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +""" + +import sys +import os +import re +import time +import shutil +import optparse +import subprocess + +class Handler: + def __init__(self): + self.marks = {} + self.files = [] + self.prevfiles = None + self.ch = None + self.line = None + self.unread_line = False + self.eof = False + self.debug = False + self.export_marks = [] + self.import_marks = [] + + def read_next_line(self): + if self.unread_line: + self.unread_line = False + return + self.line = "" + if self.eof: + return + if self.ch: + self.line += self.ch + self.ch = None + buf = sys.stdin.readline() + if not len(buf): + self.eof = True + else: + self.line += buf + if self.debug: + print "read_next_line: '%s'" % self.line + + def read(self, length): + buf = "" + if self.ch: + buf += self.ch + self.ch = None + buf += sys.stdin.read(length) + if self.debug: + print "read: '%s'" % buf + return buf + + def skip_optional_lf(self): + self.ch = self.read(1) + if self.ch == "\n": + self.ch = None + + def bug(self, s): + raise Exception(s) + + def get_date(self, ts, tz): + # int(ts) is seconds since epoch. Since we're trying to + # capture both the absolute time of the commit and the + # localtime in the timezone of the committer, we need to turn + # the (seconds-since-epoch, committer-timezone-offset) pair + # that we get from the git-fast-export stream format into a + # localized-time-plus-timezone-marker string that darcs will + # accept. Therefore, we parse the timezone-offset (which + # looks like +0500 or +0000 or -0730 or something) and add it + # to seconds-since-epoch before calling gmtime(). + mo = re.search(r'^([\+\-])(\d\d)(\d\d)$', tz) + offset = 60*60*int(mo.group(2)) + 60*int(mo.group(3)) + if mo.group(1) == "-": + offset = -offset + offset_time = int(ts) + offset + s = time.strftime("%a %b %d %H:%M:%S %Y", time.gmtime(offset_time)) + items = s.split(' ') + return " ".join(items[:-1]) + " " + tz + " " + items[-1] + + def handle_mark(self): + if self.line.startswith("mark :"): + self.mark_num = int(self.line[6:-1]) + self.read_next_line() + + def handle_data(self): + if not self.line.startswith("data "): + self.bug("Expected 'data n' command, found: '%s'" % self.line[:-1]) + length = int(self.line[5:-1]) + self.buf = self.read(length) + self.skip_optional_lf() + + def handle_blob(self): + self.read_next_line() + self.handle_mark() + self.handle_data() + self.marks[self.mark_num] = self.buf + + def handle_ident(self, s): + items = s.split(' ') + self.ident = " ".join(items[:-2]) + self.date = self.get_date(items[-2], items[-1]) + + def handle_msg(self): + items = self.buf.split('\n') + self.short = items[0] + self.long = "\n".join(items[1:]) + + def handle_tag(self): + version = self.line[:-1].split(' ')[1] + self.read_next_line() + if self.line.startswith("from "): + self.read_next_line() + if self.line.startswith("tagger "): + self.handle_ident(self.line[7:-1]) + self.read_next_line() + self.handle_data() + self.skip_optional_lf() + sock = subprocess.Popen(["darcs", "tag", "--pipe"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) + buf = [self.date, self.ident, version] + sock.stdin.write("\n".join(buf)) + sock.stdin.close() + self.log("Tagging %s:\n%s" % (version, sock.stdout.read())) + sock.stdout.close() + + def handle_commit(self): + if not self.prevfiles and self.options.import_marks: + # first commit in an incremental continued + # import + for (root, dirs, files) in os.walk("."): + for i in files: + path = os.path.normpath(os.path.join(root, i)) + if path.startswith("_darcs") or "-darcs-backup" in path: + continue + self.files.append(path) + self.prevfiles = self.files[:] + adds = [] + + self.read_next_line() + self.handle_mark() + if self.line.startswith("author "): + self.handle_ident(self.line[7:-1]) + self.read_next_line() + if self.line.startswith("committer "): + self.handle_ident(self.line[10:-1]) + self.read_next_line() + self.handle_data() + self.skip_optional_lf() + self.handle_msg() + self.read_next_line() + if self.line.startswith("from "): + self.read_next_line() + while self.line.startswith("merge "): + self.read_next_line() + while len(self.line) > 0: + if self.line.startswith("deleteall"): + path = self.line[2:-1] + for path in self.files: + os.unlink(path) + self.files = [] + elif self.line.startswith("D "): + path = self.line[2:-1] + if os.path.exists(path): + os.unlink(path) + if path in self.files: + self.files.remove(path) + elif self.line.startswith("R "): + os.system("darcs mv %s" % self.line[2:]) + elif self.line.startswith("C "): + src, dest = self.line[:-1].split(' ')[1:] + shutil.copy(src.strip('"'), dest.strip('"')) + os.system("darcs add %s" % dest) + elif self.line.startswith("M "): + items = self.line.split(' ') + path = items[3][:-1] + sock = open(path, "w") + if items[2] != "inline": + idx = int(items[2][1:]) + sock.write(self.marks[idx]) + del self.marks[idx] + else: + self.read_next_line() + self.handle_data() + sock.write(self.buf) + sock.close() + if path not in self.prevfiles: + adds.append(path) + if path not in self.files: + self.files.append(path) + else: + self.unread_line = True + break + self.read_next_line() + if not len(self.line): + break + + for i in adds: + os.system("darcs add %s" % i) + sock = subprocess.Popen(["darcs", "record", "--ignore-times", "-a", "--pipe"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) + buf = [self.date, self.ident, self.short, self.long] + sock.stdin.write("\n".join(buf)) + sock.stdin.close() + self.log("Recording :%s:\n%s" % (self.mark_num, sock.stdout.read())) + sock.stdout.close() + + if self.options.export_marks: + # yeah, an xml parser would be better, but + # should we mess with encodings just because of + # this? i hope not + sock = os.popen("darcs changes --last=1 --xml", "r") + buf = sock.read() + sock.close() + hash = buf.split('\n')[1].split("'")[-2] + self.export_marks.append(":%s %s" % (self.mark_num, hash)) + + def handle_progress(self, s): + print "progress [%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), s.strip()) + sys.stdout.flush() + + def handle_opts(self): + # Option Parser + usage="%prog [options]" + opp = optparse.OptionParser(usage=usage) + opp.add_option("--import-marks", metavar="IFILE", + help="read state for incremental imports from IFILE") + opp.add_option("--export-marks", metavar="OFILE", + help="write state for incremental imports to OFILE") + opp.add_option("--logfile", metavar="L", + help="log file which contains the output of external programs invoked during the conversion") + (self.options, args) = opp.parse_args() + + if self.options.logfile: + logfile = self.options.logfile + else: + logfile = "_darcs/import.log" + self.logsock = open(os.path.abspath(logfile), "a") + + def log(self, s): + self.logsock.write("[%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), s)) + self.logsock.flush() + + def handle_export_marks(self): + if self.options.export_marks: + sock = open(self.options.export_marks, 'w') + sock.write("\n".join(self.export_marks)) + sock.write("\n") + sock.close() + + def handle_import_marks(self): + if self.options.import_marks: + sock = open(self.options.import_marks) + for i in sock.readlines(): + line = i.strip() + if not len(line): + continue + self.import_marks.append(line.split(' ')[1]) + self.export_marks.append(line) + sock.close() + + def handle(self): + self.handle_opts() + self.handle_import_marks() + + while not self.eof: + self.read_next_line() + if not len(self.line[:-1]): + pass + elif self.line.startswith("blob"): + self.handle_blob() + elif self.line.startswith("commit"): + self.handle_commit() + elif self.line.startswith("tag"): + self.handle_tag() + elif self.line.startswith("reset"): + self.read_next_line() + if not self.line.startswith("from "): + self.unread_line = True + elif self.line.startswith("checkpoint"): + pass + elif self.line.startswith("progress"): + self.handle_progress(self.line[9:]) + else: + self.bug("'%s': invalid command" % self.line[:-1]) + + self.handle_export_marks() + +if __name__ == "__main__": + h = Handler() + h.handle() diff --git a/exporters/darcs/darcs-fast-import.txt b/exporters/darcs/darcs-fast-import.txt new file mode 100644 index 0000000..09c7b1e --- /dev/null +++ b/exporters/darcs/darcs-fast-import.txt @@ -0,0 +1,35 @@ += darcs-fast-import(1) + +== NAME + +darcs-fast-import - darcs backend to the 'fast-import stream' format + +== SYNOPSIS + +darcs-fast-import [<options>] + +== DESCRIPTION + +darcs-fast-import can produce a darcs repository from a fast-import +stream, read from the standard input. It supports incremental conversion +as well, via the --import-marks / --export-marks switches. + +== OPTIONS + +-h, --help:: + Display usage. + +--import-marks:: + Import marks from a given file. This is read at the beginning of the + conversion at once. Use it if you want to continue an incremental + conversion. + +--export-marks:: + Export marks to a given file at the end of the conversion. It can be the + same as the one for --import-marks as it is written only once at the + end. Use it if you want to be able to incrementally update the target + repository later. + +--logfile:: + The output of external commands are redirected to a log file. You can + specify the path of that file with this parameter. diff --git a/exporters/darcs/git-darcs b/exporters/darcs/git-darcs new file mode 100755 index 0000000..eb70338 --- /dev/null +++ b/exporters/darcs/git-darcs @@ -0,0 +1,264 @@ +#!/bin/bash +# +# git-darcs - bidirectional operation between a darcs repo and git +# +# Copyright (c) 2008 by Miklos Vajna <vmiklos@frugalware.org> +# +# Based on git-bzr, which is +# +# Copyright (c) 2008 Pieter de Bie <pdebie@ai.rug.nl> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +add() +{ + name="$1" + shift + location="$1" + shift + if ! [ -n "$name" -a -n "$location" ]; then + echo "Usage: git darcs add name location [darcs-fast-export options]" + exit + fi + if git remote show |grep -q $name; then + echo "There is already a remote with that name" + exit + fi + if [ -n "$(git config git-darcs.$name.location)" ]; then + echo "There is already a darcs repo with that name" + exit + fi + if [ ! -d $location/_darcs ]; then + echo "Remote is not a darcs repository" + exit + fi + git config git-darcs.$name.location $location + git config git-darcs.$name.darcs-fast-export-options "$*" + echo "Darcs repo $name added. You can fetch it with 'git darcs fetch $name'" + if ! [ -z "$*" ]; then + echo "darcs-fast-export will get options: $*" + fi +} + +get_location() +{ + l=$(git config git-darcs.$remote.location) + if [ -z "$l" ]; then + echo "Cannot find darcs remote with name '$remote'." >&2 + exit + fi + echo $l +} + +fetch() +{ + remote="$1" + shift + if ! [ -n "$remote" -a -z "$*" ]; then + echo "Usage: git darcs fetch reponame" + exit + fi + location=$(get_location $remote) + git_map=$git_dir/darcs-git/$remote-git-map + darcs_map=$git_dir/darcs-git/$remote-darcs-map + common_opts="--working $git_dir/darcs-git/repo --logfile $git_dir/darcs-git/fetch.log --git-branch=darcs/$remote" + dfe_opts=$(git config git-darcs.$remote.darcs-fast-export-options) + if [ ! -f $git_map -a ! -f $darcs_map ]; then + echo "There doesn't seem to be an existing refmap." + echo "Doing an initial import" + mkdir -p $git_dir/darcs-git + darcs-fast-export --export-marks=$darcs_map $common_opts $dfe_opts $location | \ + git fast-import --export-marks=$git_map + elif [ -f $git_map -a -f $darcs_map ]; then + echo "Updating remote $remote" + old_rev=$(git rev-parse darcs/$remote) + darcs-fast-export --import-marks=$darcs_map --export-marks=$darcs_map $common_opts $dfe_opts $location | \ + git fast-import --quiet --import-marks=$git_map --export-marks=$git_map + new_rev=$(git rev-parse darcs/$remote) + if [ "$old_rev" != "$new_rev" ]; then + echo "Fetched the following updates:" + git shortlog $old_rev..$new_rev + else + echo "Nothing fetched." + exit + fi + else + echo "One of the mapfiles is missing! Something went wrong!" + exit + fi +} + +pull() +{ + remote="$1" + shift + if ! [ -n "$remote" -a -z "$*" ]; then + echo "Usage: git darcs pull reponame" + exit + fi + fetch $remote + # see if we need to merge or rebase + branch=$(git symbolic-ref HEAD|sed 's|.*/||') + if [ "$(git config branch.$branch.rebase)" = "true" ]; then + git rebase darcs/$remote + else + git merge darcs/$remote + fi +} + +push() +{ + remote="$1" + shift + if ! [ -n "$remote" -a -z "$*" ]; then + echo "Usage: git darcs push reponame" + exit + fi + location=$(get_location $remote) + if [ -n "$(git rev-list --left-right HEAD...darcs/$remote | sed -n '/^>/ p')" ]; then + echo "HEAD is not a strict child of $remote, cannot push. Merge first" + exit + fi + if [ -z "$(git rev-list --left-right HEAD...darcs/$remote | sed -n '/^</ p')" ]; then + echo "Nothing to push. Commit something first" + exit + fi + git_map=$git_dir/darcs-git/$remote-git-map + darcs_map=$git_dir/darcs-git/$remote-darcs-map + if [ ! -f $git_map -o ! -f $darcs_map ]; then + echo "We do not have refmapping yet. Then how can I push?" + exit + fi + echo "Pushing the following updates:" + git shortlog darcs/$remote.. + git fast-export --import-marks=$git_map --export-marks=$git_map HEAD | \ + (cd $location; darcs-fast-import --import-marks=$darcs_map --export-marks=$darcs_map \ + --logfile $git_dir/darcs-git/push.log) + if [ $? == 0 ]; then + git update-ref darcs/$remote HEAD + fi +} + +# List the darcs remotes +list() +{ + if [ -z "$*" ] + then + git config -l | sed -n -e '/git-darcs\..*/ {s/git-darcs\.//; s/\.location=.*//p}' + exit + elif [ "$#" -eq 1 ] + then + case $1 in + -v|--verbose) + git config -l | sed -n -e '/git-darcs\..*/ {s/git-darcs\.//; s/\.location=/\t/p}' + exit + ;; + esac + fi + echo "Usage: git darcs list [-v|--verbose]" + exit 1 +} + +# Find the darcs commit(s) supporting a git SHA1 prefix +find_darcs() +{ + sha1="$1" + shift + if [ -z "$sha1" -o -n "$*" ] + then + echo "Usage: git darcs find-darcs <sha1-prefix>" + exit 1 + fi + for remote in $git_dir/darcs/* + do + remote=`basename $remote` + git_map=$git_dir/darcs-git/$remote-git-map + darcs_map=$git_dir/darcs-git/$remote-darcs-map + if [ ! -f $git_map -o ! -f $darcs_map ] + then + echo "Missing mappings for remote $remote" + exit 1 + fi + for row in `sed -n -e "/:.* $sha1.*/ s/[^ ]*/&/p" $git_map` + do + sed -n -e "/$row / {s/[^ ]*//; s/.*/$remote\t&/p}" $darcs_map + done + done +} + +# Find the git commit(s) supporting a darcs patch prefix +find_git() +{ + patch="$1" + shift + if [ -z "$patch" -o -n "$*" ] + then + echo "Usage: git darcs find-git <patch-prefix>" + exit 1 + fi + for remote in $git_dir/darcs/* + do + remote=`basename $remote` + git_map=$git_dir/darcs-git/$remote-git-map + darcs_map=$git_dir/darcs-git/$remote-darcs-map + if [ ! -f $git_map -o ! -f $darcs_map ] + then + echo "Missing mappings for remote $remote" + exit 1 + fi + for row in `sed -n -e "/:.* $patch.*/ s/[^ ]*/&/p" $darcs_map` + do + sed -n -e "/$row / {s/[^ ]* \(.*\)/$remote\t\1/p}" $git_map + done + done +} + +git rev-parse 2> /dev/null +if [ $? != 0 ]; then + echo "Must be inside a git repository to work" + exit +fi + +git_dir=$(git rev-parse --git-dir) +# make it absolute +cd $git_dir +git_dir=$(pwd) +cd - >/dev/null +command="$1" +shift + +case $command in + add|push|fetch|pull|list) + ;; + find-darcs) + command=find_darcs + ;; + find-git) + command=find_git + ;; + *) + echo "Usage: git darcs [COMMAND] [OPTIONS]" + echo "Commands: add, push, fetch, pull, list, find-darcs, find-git" + exit + ;; +esac + + +up=$(git rev-parse --show-cdup) +[ -z "$up" ] && up="." +cd $up +$command "$@" diff --git a/exporters/darcs/git-darcs.txt b/exporters/darcs/git-darcs.txt new file mode 100644 index 0000000..7558329 --- /dev/null +++ b/exporters/darcs/git-darcs.txt @@ -0,0 +1,72 @@ += git-darcs(1) + +== NAME + +git-darcs - a bidirectional git - darcs gateway + +== SYNOPSIS + +git-darcs <command> <options> + +== DESCRIPTION + +git darcs can convert a darcs repo to a git one, can update such an +existing git repo later, and finally can push back your changes from the +git repo to the darcs one. + +A typical workflow is: + +---- +$ mkdir git-repo +$ cd git-repo +$ git init +$ git darcs add upstream ../darcs-repo +$ git darcs pull upstream + +... hack, hack, hack ... + +$ git darcs push upstream +---- + +== GLOBAL OPTIONS + +-h, --help:: + Display usage. + +== COMMANDS + +The supported commands are the followings: + +add:: + This can register a new darcs repo in the git one, so that you + can fetch from it. The syntax is `add nick path [dfe-options]`. + Add any options you want to be passed to darcs-fast-export, + like --encoding=utf-8, or --authors-file AUTHORMAP. Remember + that if AUTHORMAP is not absolute, it will be interpreted + relative to the git repository's root directory. + +push:: + Transfers your changes created in the current branch back the + darcs one. The syntax is `push nick`. + +fetch:: + Downloads changes from the darcs repo and updates the + `darcs/<nick>` branch. None of your local branches are updated. + +pull:: + Calls `fetch` then `git merge` or `git rebase` based on the + `branch.<branchname>.rebase` configuration setting, where `<branchname>` + is the current branch. The default is - just like with `git pull` - is + to `git merge`. + +list:: + List the name [and location] of each registered darcs repo. + The syntax is `list [-v|--verbose]`. + +find-darcs:: + Searches for darcs patches matching a SHA1 prefix. + The syntax is `find-darcs <sha1-prefix>`. + +find-git:: + Searches for git commits matching a darcs patch prefix. + The syntax is `find-git <patch-prefix>`. diff --git a/exporters/darcs/t/Makefile b/exporters/darcs/t/Makefile new file mode 100644 index 0000000..de8a7ab --- /dev/null +++ b/exporters/darcs/t/Makefile @@ -0,0 +1,9 @@ +T = $(wildcard test*.sh) + +all: $(T) + @echo "passed $$(echo $(T)|wc -w) tests." + +$(T): + @echo "*** $@ ***"; sh $@ + +.PHONY: $(T) diff --git a/exporters/darcs/t/bench-results/Makefile b/exporters/darcs/t/bench-results/Makefile new file mode 100644 index 0000000..0157f69 --- /dev/null +++ b/exporters/darcs/t/bench-results/Makefile @@ -0,0 +1,5 @@ +bench-results.png: bench-results.gnu bench-results.dat + gnuplot bench-results.gnu + +bench-results.dat: bench-results.py $(wildcard ../darcs-benchmark/big-zoo/*.log) + python bench-results.py > bench-results.dat diff --git a/exporters/darcs/t/bench-results/bench-results.gnu b/exporters/darcs/t/bench-results/bench-results.gnu new file mode 100644 index 0000000..f4e8917 --- /dev/null +++ b/exporters/darcs/t/bench-results/bench-results.gnu @@ -0,0 +1,6 @@ +set terminal png +set output 'bench-results.png' +unset key +set xlabel "number of patches" +set ylabel "elapsed time in hours" +plot 'bench-results.dat' with linespoints diff --git a/exporters/darcs/t/bench-results/bench-results.py b/exporters/darcs/t/bench-results/bench-results.py new file mode 100644 index 0000000..fbb834b --- /dev/null +++ b/exporters/darcs/t/bench-results/bench-results.py @@ -0,0 +1,23 @@ +from glob import glob +import re + +def cmp_data(a, b): + return cmp(a[0], b[0]) + +logs = glob("../darcs-benchmark/big-zoo/*.log") + +data = [] + +for i in logs: + sock = open(i) + for j in sock.readlines(): + if "Num Patches:" in j: + patches = int(j.split(": ")[1].strip()) + elif j.startswith("real"): + l = re.sub("real\t([0-9]+)m([0-9.]+)s\n", r"\1 \2", j).split(" ") + secs = int(l[0])*60 + float(l[1]) + hours = secs / 3600 + data.append([patches, hours]) +data.sort(cmp=cmp_data) +for i in data: + print "%s %s" % (i[0], i[1]) diff --git a/exporters/darcs/t/bench-tailor.sh b/exporters/darcs/t/bench-tailor.sh new file mode 100644 index 0000000..7567f7b --- /dev/null +++ b/exporters/darcs/t/bench-tailor.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +create_config() +{ + cd $1 + mypath=$(pwd) + cd - >/dev/null + myname=$(basename $mypath) + + cat > config << EOF +[DEFAULT] +encoding-errors-policy = replace + +[$myname] +source = darcs:$myname +target = git:$myname + +[darcs:$myname] +subdir = darcs +repository = $mypath + +[git:$myname] +subdir = git +repository = $mypath.git +EOF +} + +PATH=$HOME/darcs/tailor:$PATH +if [ ! -d darcs-benchmark ]; then + darcs get http://code.haskell.org/darcs/darcs-benchmark + cd darcs-benchmark +else + cd darcs-benchmark + darcs pull -a +fi +sh initialise.sh +cd big-zoo +if [ -n "$1" ]; then + targets=$1 +else + targets=*_play.tar.gz +fi +for i in $targets +do + echo "benchmarking $i" + rm -rf _playground + tar xf $i + cd _playground + log="../$i.tailor-$(tailor --version).log" + create_config sandbox + sh -c 'time tailor --configfile config' 2>&1 |tee $log + if diff --exclude _darcs --exclude .git -Nur sandbox git >/dev/null; then + echo "ok, the result is correct" >> $log + else + echo "ouch, the result is corrupted" >> $log + exit 1 + fi + cd .. +done diff --git a/exporters/darcs/t/bench.sh b/exporters/darcs/t/bench.sh new file mode 100644 index 0000000..a4b3d0d --- /dev/null +++ b/exporters/darcs/t/bench.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# this is a test as well, but it would take a lot of time, so don't +# prefix it with 'test'. + +. lib.sh + +if [ ! -d darcs-benchmark ]; then + darcs get http://code.haskell.org/darcs/darcs-benchmark + cd darcs-benchmark +else + cd darcs-benchmark + darcs pull -a +fi +sh initialise.sh +cd big-zoo +if [ -n "$1" ]; then + targets=$1 +else + targets=*_play.tar.gz +fi +for i in $targets +do + echo "benchmarking $i" + rm -rf _playground + tar xf $i + cd _playground + log="../$i.d-f-e-$(git describe).log" + sh -c 'time d2x -f git sandbox' 2>&1 |tee $log + darcs show repo --repodir sandbox |egrep -v 'Root|Cache|Default' >> $log + if diff_git sandbox >/dev/null; then + echo "ok, the result is correct" >> $log + else + echo "ouch, the result is corrupted" >> $log + exit 1 + fi + cd .. +done diff --git a/exporters/darcs/t/data/hungarian.gif b/exporters/darcs/t/data/hungarian.gif Binary files differnew file mode 100644 index 0000000..41a36fe --- /dev/null +++ b/exporters/darcs/t/data/hungarian.gif diff --git a/exporters/darcs/t/lib.sh b/exporters/darcs/t/lib.sh new file mode 100644 index 0000000..3df0a8a --- /dev/null +++ b/exporters/darcs/t/lib.sh @@ -0,0 +1,303 @@ +export DARCS_EMAIL="user@example.com" +export GIT_PAGER=cat +export PATH="$(pwd)/..:$PATH" +pypath="/$(python -c 'from distutils import sysconfig; print sysconfig.get_python_lib()[1:]')/" + +_drrec() +{ + darcs rec --ignore-times "$@" +} + +_drrec_multiline() +{ + echo -e "`LANG= LC_ALL= date +"%a %b %d %H:%M:%S %Z %Y"` +$DARCS_EMAIL +$@" | darcs rec --ignore-times -a --pipe . +} + +_drrecamend() +{ + echo y |darcs amend-rec --ignore-times -a +} + +create_darcs() +{ + rm -rf $1 + mkdir -p $1 + cd $1 + darcs init $2 + echo A > file + darcs add file + _drrec -a -m A + cd .. + rm -rf $1.tmp + darcs get $1 $1.tmp + cd $1 + echo B > file + _drrec -a -m B + cd ../$1.tmp + echo C > file + _drrec -a -m C + cd ../$1 + darcs pull -a ../$1.tmp + echo D > file + _drrec_multiline "first line +second line +third line" + darcs tag 1.0 + echo e > file + _drrec -a -m e + echo f > file + _drrec --author="éáõû <$DARCS_EMAIL>" -a -m f + echo g > file + _drrec --author="" -a -m g + cp ../data/hungarian.gif . + darcs add hungarian.gif + _drrec -a -m "add a binary file" + rm file + echo test > file2 + darcs add file2 + _drrec -a -m "replace file with file2" + touch file3 + darcs add file3 + _drrec -a -m "add empty file" + rm file3 + _drrec -a -m "remove file" + mkdir dir dir2 + darcs add dir + darcs add dir2 + _drrec -a -m "add empty dirs" + darcs mv dir dir-p + darcs mv dir2 dir2-p + _drrec -a -m "rename empty dirs" + echo a > a + echo b > b + darcs add a b + _drrec -a -m "add a b" + rm b + _drrec -a -m "remove and rename" + darcs mv a b + _drrecamend + cd .. +} + +create_bzr() +{ + rm -rf $1 + mkdir -p $1 + cd $1 + bzr init $2 + echo A > file + bzr add file + bzr commit -m A + cd .. + rm -rf $1.tmp + bzr branch $1 $1.tmp + cd $1 + echo B > file + bzr commit -m B + cd ../$1.tmp + echo C > file + bzr commit -m C + cd ../$1 + bzr merge ../$1.tmp + echo D > file + bzr resolve file + echo "first line +second line +third line" | bzr commit -F /dev/stdin + bzr tag 1.0 + echo e > file + bzr commit -m e + #echo f > file + #bzr commit --author="éáõû <$DARCS_EMAIL>" -m f + #echo g > file + #_drrec --author="" -a -m g + cp ../data/hungarian.gif . + bzr add hungarian.gif + bzr commit -m "add a binary file" + rm file + echo test > file2 + bzr add file2 + bzr commit -m "replace file with file2" + touch file3 + bzr add file3 + bzr commit -m "add empty file" + rm file3 + bzr commit -m "remove file" + cd .. +} + +create_hg() +{ + rm -rf $1 + mkdir -p $1 + cd $1 + hg init $2 + echo A > file + hg add file + hg commit -m A + cd .. + rm -rf $1.tmp + hg clone $1 $1.tmp + cd $1 + echo B > file + hg commit -m B + cd ../$1.tmp + echo C > file + hg commit -m C + cd ../$1 + hg pull ../$1.tmp + hg merge + echo D > file + echo "first line +second line +third line" | hg commit -l /dev/stdin + hg tag 1.0 + echo e > file + hg commit -m e + #echo f > file + #bzr commit --author="éáõû <$DARCS_EMAIL>" -m f + #echo g > file + #_drrec --author="" -a -m g + cp ../data/hungarian.gif . + hg add hungarian.gif + hg commit -m "add a binary file" + hg rm file + echo test > file2 + hg add file2 + hg commit -m "replace file with file2" + touch file3 + hg add file3 + hg commit -m "add empty file" + hg rm file3 + hg commit -m "remove file" + cd .. +} +create_git() +{ + rm -rf $1 + mkdir -p $1 + cd $1 + git init $2 + echo A > file + git add file + git commit -a -m A + echo B > file + git commit -a -m B + git checkout -b tmp HEAD~1 + echo C > file + git commit -a -m C + git checkout master + git merge tmp + echo D > file + echo "first line +second line +third line" | git commit -a -F - + git branch -d tmp + git tag 1.0 + echo e > file + git commit -a -m e + echo f > file + git config i18n.commitencoding ISO-8859-2 + git commit --author="éáõû <$DARCS_EMAIL>" -a -m f + cp ../data/hungarian.gif . + git add hungarian.gif + git commit -a -m "add a binary file" + rm file + echo test > file2 + git add file2 + git commit -a -m "replace file with file2" + touch file3 + git add file3 + git commit -a -m "add empty file" + rm file3 + git commit -a -m "remove file" + cd .. +} + +diff_git() +{ + rm -rf $1.git.nonbare + git clone -q $1.git $1.git.nonbare + diff --exclude _darcs --exclude .git --exclude '*-darcs-backup*' -Nur $1.git.nonbare $1 + return $? +} + +diff_importgit() +{ + diff --exclude _darcs --exclude .git --exclude '*-darcs-backup*' -Nur $1 $1.darcs + return $? +} + +diff_importhg() +{ + diff --exclude _darcs --exclude .hg --exclude '*-darcs-backup*' --exclude 'hg-export.*' \ + --exclude '.hgtags' --exclude '*.orig' -Nur $1 $1.darcs + return $? +} + +diff_importdarcs() +{ + diff --exclude _darcs --exclude '*-darcs-backup*' -Nur $1 $2 + return $? +} + +diff_importbzr() +{ + diff --exclude _darcs --exclude .bzr --exclude '*-darcs-backup*' -Nur $1 $1.darcs + return $? +} + +diff_bzr() +{ + cd $1.bzr/trunk + bzr update + cd - >/dev/null + diff --exclude _darcs --exclude .bzr --exclude '*-darcs-backup*' -Nur $1.bzr/trunk $1 + return $? +} + +diff_hg() +{ + diff --exclude _darcs --exclude .hg --exclude '*-darcs-backup*' -Nur $1.hg $1 + return $? +} + +die() +{ + echo "fatal: $@" + exit 1 +} + +upd_file_darcs() +{ + cd $1 + echo $3 > $2 + _drrec -a -m "updated '$2' to '$3'" + cd .. +} + +upd_file_git() +{ + cd $1 + echo $3 > $2 + git commit -a -m "updated '$2' to '$3'" + cd .. +} + +upd_file_bzr() +{ + cd $1 + echo $3 > $2 + bzr commit -m "updated '$2' to '$3'" + cd .. +} + +upd_file_hg() +{ + cd $1 + echo $3 > $2 + hg commit -m "updated '$2' to '$3'" + cd .. +} diff --git a/exporters/darcs/t/test-bzr.sh b/exporters/darcs/t/test-bzr.sh new file mode 100644 index 0000000..778b778 --- /dev/null +++ b/exporters/darcs/t/test-bzr.sh @@ -0,0 +1,16 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.darcs test.bzr +mkdir test.bzr +cd test.bzr +bzr init-repo . +cd .. +if [ "$1" != "--stdout" ]; then + darcs-fast-export test |(cd test.bzr; bzr fast-import -) + diff_bzr test + exit $? +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test-git-d2x.sh b/exporters/darcs/t/test-git-d2x.sh new file mode 100644 index 0000000..60868be --- /dev/null +++ b/exporters/darcs/t/test-git-d2x.sh @@ -0,0 +1,19 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.git +if [ "$1" != "--stdout" ]; then + d2x -f git test + diff_git test || die "initial conversion differs" + upd_file_darcs test file2 upd_contents + d2x -f git test + diff_git test || die "update differs" + upd_file_darcs test hungarian.gif "binary to text" + d2x -f git test + diff_git test || die "update2 differs" + d2x -f git test + diff_git test || die "update3 (noop) differs" +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test-git-incremental.sh b/exporters/darcs/t/test-git-incremental.sh new file mode 100644 index 0000000..0b822e7 --- /dev/null +++ b/exporters/darcs/t/test-git-incremental.sh @@ -0,0 +1,24 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.darcs test.git +mkdir test.git +cd test.git +git --bare init +cd .. +if [ "$1" != "--stdout" ]; then + dmark="$(pwd)/test.dfe-marks" + gmark="$(pwd)/test.gfi-marks" + rm -f $mark $gmark + darcs-fast-export --export-marks=$dmark test |(cd test.git; git fast-import --export-marks=$gmark) + diff_git test || die "initial conversion differs" + upd_file_darcs test file2 upd_contents + darcs-fast-export --export-marks=$dmark --import-marks=$dmark test |(cd test.git; git fast-import --export-marks=$gmark --import-marks=$gmark) + diff_git test || die "update differs" + upd_file_darcs test hungarian.gif "binary to text" + darcs-fast-export --export-marks=$dmark --import-marks=$dmark test |(cd test.git; git fast-import --export-marks=$gmark --import-marks=$gmark) + diff_git test || die "update2 differs" +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test-git-progress.sh b/exporters/darcs/t/test-git-progress.sh new file mode 100644 index 0000000..1eb371c --- /dev/null +++ b/exporters/darcs/t/test-git-progress.sh @@ -0,0 +1,18 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.darcs test.git +mkdir test.git +cd test.git +git --bare init +cd .. +if [ "$1" != "--stdout" ]; then + darcs-fast-export --progres 2 test |(cd test.git; git fast-import) + if [ $? = 0 ]; then + diff_git test + exit $? + fi +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test-git.sh b/exporters/darcs/t/test-git.sh new file mode 100644 index 0000000..c95fa94 --- /dev/null +++ b/exporters/darcs/t/test-git.sh @@ -0,0 +1,18 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.darcs test.git +mkdir test.git +cd test.git +git --bare init +cd .. +if [ "$1" != "--stdout" ]; then + darcs-fast-export test |(cd test.git; git fast-import) + if [ $? = 0 ]; then + diff_git test + exit $? + fi +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test-hg-d2x.sh b/exporters/darcs/t/test-hg-d2x.sh new file mode 100644 index 0000000..cc59bbe --- /dev/null +++ b/exporters/darcs/t/test-hg-d2x.sh @@ -0,0 +1,12 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.hg +if [ "$1" != "--stdout" ]; then + d2x -f hg test + diff_hg test + exit $? +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test-hg.sh b/exporters/darcs/t/test-hg.sh new file mode 100644 index 0000000..9827375 --- /dev/null +++ b/exporters/darcs/t/test-hg.sh @@ -0,0 +1,16 @@ +. lib.sh + +create_darcs test --old-fashioned-inventory + +rm -rf test.darcs test.hg +mkdir test.hg +cd test.hg +hg init +cd .. +if [ "$1" != "--stdout" ]; then + darcs-fast-export test |(cd test.hg; hg fastimport /dev/stdin) + diff_hg test + exit $? +else + darcs-fast-export test +fi diff --git a/exporters/darcs/t/test2-bzr-d2x.sh b/exporters/darcs/t/test2-bzr-d2x.sh new file mode 100644 index 0000000..28820d9 --- /dev/null +++ b/exporters/darcs/t/test2-bzr-d2x.sh @@ -0,0 +1,19 @@ +. lib.sh + +create_darcs test2 --darcs-2 + +rm -rf test2.bzr +if [ "$1" != "--stdout" ]; then + d2x -f bzr test2 + diff_bzr test2 || die "initial conversion differs" + upd_file_darcs test2 file2 upd_contents + d2x -f bzr test2 + diff_bzr test2 || die "update differs" + upd_file_darcs test2 hungarian.gif "binary to text" + d2x -f bzr test2 + diff_bzr test2 || die "update2 differs" + d2x -f bzr test2 + diff_bzr test2 || die "update3 (noop) differs" +else + darcs-fast-export test2 +fi diff --git a/exporters/darcs/t/test2-bzr-incremental.sh b/exporters/darcs/t/test2-bzr-incremental.sh new file mode 100644 index 0000000..ece1623 --- /dev/null +++ b/exporters/darcs/t/test2-bzr-incremental.sh @@ -0,0 +1,21 @@ +. lib.sh + +create_darcs test2 --darcs-2 + +rm -rf test2.darcs test2.bzr +mkdir test2.bzr +cd test2.bzr +bzr init-repo . +cd .. +if [ "$1" != "--stdout" ]; then + dmark="$(pwd)/test2.dfe-marks" + bmark="$(pwd)/test2.bfi-marks" + rm -f $mark $gmark + darcs-fast-export --export-marks=$dmark test2 |(cd test2.bzr; bzr fast-import --export-marks=$bmark -) + diff_bzr test2 || die "initial conversion differs" + upd_file_darcs test2 file2 upd_contents + darcs-fast-export --export-marks=$dmark --import-marks=$dmark test2 |(cd test2.bzr; bzr fast-import --export-marks=$bmark --import-marks=$bmark -) + diff_bzr test2 || die "update differs" +else + darcs-fast-export test2 +fi diff --git a/exporters/darcs/t/test2-git-funny-tagname.sh b/exporters/darcs/t/test2-git-funny-tagname.sh new file mode 100644 index 0000000..ae1465f --- /dev/null +++ b/exporters/darcs/t/test2-git-funny-tagname.sh @@ -0,0 +1,25 @@ +. lib.sh + +create_darcs test2 --darcs-2 +cd test2 +darcs tag "this :just (won't work; die)" +darcs tag "accent-tag-éáőű" +cd .. + +rm -rf test2.darcs test2.git +mkdir test2.git +cd test2.git +git --bare init +cd .. +if [ "$1" != "--stdout" ]; then + darcs-fast-export test2 |(cd test2.git; git fast-import) + ret=$? + if [ $ret = 0 ]; then + diff_git test2 + exit $? + else + exit $ret + fi +else + darcs-fast-export test2 +fi diff --git a/exporters/darcs/t/test2-git-incremental-specworkdir.sh b/exporters/darcs/t/test2-git-incremental-specworkdir.sh new file mode 100644 index 0000000..937bb46 --- /dev/null +++ b/exporters/darcs/t/test2-git-incremental-specworkdir.sh @@ -0,0 +1,22 @@ +. lib.sh + +create_darcs test2 --darcs-2 + +rm -rf test2.darcs test2.git +mkdir test2.git +cd test2.git +git --bare init +mkdir darcs +cd .. +if [ "$1" != "--stdout" ]; then + dmark="$(pwd)/test2.git/darcs/test2.dfe-marks" + gmark="$(pwd)/test2.git/darcs/test2.gfi-marks" + rm -f $mark $gmark + darcs-fast-export --export-marks=$dmark test2 --working test2.git/darcs/repo |(cd test2.git; git fast-import --export-marks=$gmark) + diff_git test2 || die "initial conversion differs" + upd_file_darcs test2 file2 upd_contents + darcs-fast-export --export-marks=$dmark --import-marks=$dmark test2 --working test2.git/darcs/repo |(cd test2.git; git fast-import --export-marks=$gmark --import-marks=$gmark) + diff_git test2 || die "update differs" +else + darcs-fast-export test2 +fi diff --git a/exporters/darcs/t/test2-git-incremental.sh b/exporters/darcs/t/test2-git-incremental.sh new file mode 100644 index 0000000..1afcfc1 --- /dev/null +++ b/exporters/darcs/t/test2-git-incremental.sh @@ -0,0 +1,21 @@ +. lib.sh + +create_darcs test2 --darcs-2 + +rm -rf test2.darcs test2.git +mkdir test2.git +cd test2.git +git --bare init +cd .. +if [ "$1" != "--stdout" ]; then + dmark="$(pwd)/test2.dfe-marks" + gmark="$(pwd)/test2.gfi-marks" + rm -f $mark $gmark + darcs-fast-export --export-marks=$dmark test2 |(cd test2.git; git fast-import --export-marks=$gmark) + diff_git test2 || die "initial conversion differs" + upd_file_darcs test2 file2 upd_contents + darcs-fast-export --export-marks=$dmark --import-marks=$dmark test2 |(cd test2.git; git fast-import --export-marks=$gmark --import-marks=$gmark) + diff_git test2 || die "update differs" +else + darcs-fast-export test2 +fi diff --git a/exporters/darcs/t/test2-git.sh b/exporters/darcs/t/test2-git.sh new file mode 100644 index 0000000..8c723de --- /dev/null +++ b/exporters/darcs/t/test2-git.sh @@ -0,0 +1,18 @@ +. lib.sh + +create_darcs test2 --darcs-2 + +rm -rf test2.darcs test2.git +mkdir test2.git +cd test2.git +git --bare init +cd .. +if [ "$1" != "--stdout" ]; then + darcs-fast-export test2 |(cd test2.git; git fast-import) + if [ $? = 0 ]; then + diff_git test2 + exit $? + fi +else + darcs-fast-export test2 +fi diff --git a/exporters/darcs/t/testimport-bzr-x2d.sh b/exporters/darcs/t/testimport-bzr-x2d.sh new file mode 100644 index 0000000..790bbfd --- /dev/null +++ b/exporters/darcs/t/testimport-bzr-x2d.sh @@ -0,0 +1,15 @@ +. lib.sh + +create_bzr test + +rm -rf test.darcs +x2d -f bzr test +diff_importbzr test || die "initial conversion differs" +upd_file_bzr test file2 upd_contents +x2d -f bzr test +diff_importbzr test || die "update differs" +upd_file_bzr test hungarian.gif "binary to text" +x2d -f bzr test +diff_importbzr test || die "update2 differs" +x2d -f bzr test +diff_importbzr test || die "update3 (noop) differs" diff --git a/exporters/darcs/t/testimport-bzr.sh b/exporters/darcs/t/testimport-bzr.sh new file mode 100644 index 0000000..fc899b7 --- /dev/null +++ b/exporters/darcs/t/testimport-bzr.sh @@ -0,0 +1,15 @@ +. lib.sh + +create_bzr test + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +(cd test; bzr fast-export .) | (cd test.darcs; darcs-fast-import) +if [ $? != 0 ]; then + exit 1 +fi +diff_importbzr test +exit $? diff --git a/exporters/darcs/t/testimport-copy.sh b/exporters/darcs/t/testimport-copy.sh new file mode 100644 index 0000000..37b8bc0 --- /dev/null +++ b/exporters/darcs/t/testimport-copy.sh @@ -0,0 +1,26 @@ +. lib.sh + +rm -rf test +mkdir test +cd test +git init +echo a > file +git add file +git commit -m a1 +cp file file2 +git add file2 +git commit -m b +cd .. + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +(cd test; git fast-export -C -C HEAD) > out +cat out | (cd test.darcs; darcs-fast-import) +if [ $? != 0 ]; then + exit 1 +fi +diff_importgit test +exit $? diff --git a/exporters/darcs/t/testimport-darcs.sh b/exporters/darcs/t/testimport-darcs.sh new file mode 100644 index 0000000..b003dfd --- /dev/null +++ b/exporters/darcs/t/testimport-darcs.sh @@ -0,0 +1,17 @@ +. lib.sh + +create_darcs test2 --darcs-2 + +rm -rf test2.importdarcs test2.darcs +mkdir test2.importdarcs +cd test2.importdarcs +darcs init +cd .. + +darcs-fast-export test2 | (cd test2.importdarcs; darcs-fast-import) + +if [ $? != 0 ]; then + exit 1 +fi +diff_importdarcs test2 test2.importdarcs +exit $? diff --git a/exporters/darcs/t/testimport-deleteall.sh b/exporters/darcs/t/testimport-deleteall.sh new file mode 100644 index 0000000..dd10976 --- /dev/null +++ b/exporters/darcs/t/testimport-deleteall.sh @@ -0,0 +1,31 @@ +. lib.sh + +rm -rf test +mkdir test +cd test +git init +echo a > file +git add file +echo A > file2 +git add file2 +git commit -m a12 +git rm file* +echo b>file3 +git add file3 +git commit -m b +cd .. + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +(cd test; git fast-export --progress=2 HEAD) > out +sed -i '/^D file$/d' out +sed -i 's/^D file2$/deleteall/' out +cat out | (cd test.darcs; darcs-fast-import) +if [ $? != 0 ]; then + exit 1 +fi +diff_importgit test +exit $? diff --git a/exporters/darcs/t/testimport-git-incremental.sh b/exporters/darcs/t/testimport-git-incremental.sh new file mode 100644 index 0000000..dbd3600 --- /dev/null +++ b/exporters/darcs/t/testimport-git-incremental.sh @@ -0,0 +1,16 @@ +. lib.sh + +create_git test + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +gmark="$(pwd)/test.gfe-marks" +dmark="$(pwd)/test.dfi-marks" +(cd test; git fast-export --export-marks=$gmark HEAD) | (cd test.darcs; darcs-fast-import --export-marks=$dmark) +diff_importgit test || die "initial conversion differs" +upd_file_git test file2 upd_contents +(cd test; git fast-export --export-marks=$gmark --import-marks=$gmark HEAD) | (cd test.darcs; darcs-fast-import --export-marks=$dmark --import-marks=$dmark) +diff_importgit test || die "update differs" diff --git a/exporters/darcs/t/testimport-git-twoway-gd.sh b/exporters/darcs/t/testimport-git-twoway-gd.sh new file mode 100644 index 0000000..ec8b5d5 --- /dev/null +++ b/exporters/darcs/t/testimport-git-twoway-gd.sh @@ -0,0 +1,34 @@ +. lib.sh + +create_darcs test + +rm -rf test.git +mkdir test.git +cd test.git +git init +git darcs add upstream ../test +git darcs pull upstream +cd .. +diff_git test || die "initial fetch differs" +upd_file_darcs test file2 upd_contents +cd test.git +git darcs pull upstream +cd .. +diff_git test || die "fetch #1 differs" +upd_file_git test.git file2 upd_contents2 +cd test.git +git darcs push upstream +cd .. +diff_git test || die "push #1 difers" +upd_file_darcs test file2 upd_contents3 +upd_file_darcs test file2 upd_contents32 +cd test.git +git darcs pull upstream +cd .. +diff_git test || die "fetch #2 (multiple commits) differs" +upd_file_git test.git file2 upd_contents4 +upd_file_git test.git file2 upd_contents42 +cd test.git +git darcs push upstream +cd .. +diff_git test || die "push #2 (multiple commits) differs" diff --git a/exporters/darcs/t/testimport-git-twoway.sh b/exporters/darcs/t/testimport-git-twoway.sh new file mode 100644 index 0000000..a3b930c --- /dev/null +++ b/exporters/darcs/t/testimport-git-twoway.sh @@ -0,0 +1,30 @@ +. lib.sh + +create_git test + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +gmark="$(pwd)/test.gmarks" +dmark="$(pwd)/test.dmarks" + +(cd test; git fast-export --export-marks=$gmark HEAD) | (cd test.darcs; darcs-fast-import --export-marks=$dmark) +diff_importgit test || die "initial conversion differs" +upd_file_git test file2 upd_contents +(cd test; git fast-export --export-marks=$gmark --import-marks=$gmark HEAD) | (cd test.darcs; darcs-fast-import --export-marks=$dmark --import-marks=$dmark) +diff_importgit test || die "git -> darcs update #1 differs" +upd_file_darcs test.darcs file2 upd_contents2 +darcs-fast-export --export-marks=$dmark --import-marks=$dmark --working test/.git/darcs test.darcs | (cd test; git fast-import --export-marks=$gmark --import-marks=$gmark) +(cd test; git checkout -f) +diff_importgit test || die "darcs -> git update #2 differs" +upd_file_git test file2 upd_contents3 +upd_file_git test file2 upd_contents32 +(cd test; git fast-export --export-marks=$gmark --import-marks=$gmark HEAD) | (cd test.darcs; darcs-fast-import --export-marks=$dmark --import-marks=$dmark) +diff_importgit test || die "git -> darcs update #3 differs" +upd_file_darcs test.darcs file2 upd_contents4 +upd_file_darcs test.darcs file2 upd_contents42 +darcs-fast-export --export-marks=$dmark --import-marks=$dmark --working test/.git/darcs test.darcs | (cd test; git fast-import --export-marks=$gmark --import-marks=$gmark) +(cd test; git checkout -f) +diff_importgit test || die "darcs -> git update #4 differs" diff --git a/exporters/darcs/t/testimport-git-x2d.sh b/exporters/darcs/t/testimport-git-x2d.sh new file mode 100644 index 0000000..22871c5 --- /dev/null +++ b/exporters/darcs/t/testimport-git-x2d.sh @@ -0,0 +1,15 @@ +. lib.sh + +create_git test + +rm -rf test.darcs +x2d -f git test +diff_importgit test || die "initial conversion differs" +upd_file_git test file2 upd_contents +x2d -f git test +diff_importgit test || die "update differs" +upd_file_git test hungarian.gif "binary to text" +x2d -f git test +diff_importgit test || die "update2 differs" +x2d -f git test +diff_importgit test || die "update3 (noop) differs" diff --git a/exporters/darcs/t/testimport-git.sh b/exporters/darcs/t/testimport-git.sh new file mode 100644 index 0000000..48a219c --- /dev/null +++ b/exporters/darcs/t/testimport-git.sh @@ -0,0 +1,15 @@ +. lib.sh + +create_git test + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +(cd test; git fast-export --progress=2 HEAD) | (cd test.darcs; darcs-fast-import) +if [ $? != 0 ]; then + exit 1 +fi +diff_importgit test +exit $? diff --git a/exporters/darcs/t/testimport-hg-x2d.sh b/exporters/darcs/t/testimport-hg-x2d.sh new file mode 100644 index 0000000..f6869f5 --- /dev/null +++ b/exporters/darcs/t/testimport-hg-x2d.sh @@ -0,0 +1,15 @@ +. lib.sh + +create_hg test + +rm -rf test.darcs +x2d -f hg test +diff_importhg test || die "initial conversion differs" +upd_file_hg test file2 upd_contents +x2d -f hg test +diff_importhg test || die "update differs" +upd_file_hg test hungarian.gif "binary to text" +x2d -f hg test +diff_importhg test || die "update2 differs" +x2d -f hg test +diff_importhg test || die "update3 (noop) differs" diff --git a/exporters/darcs/t/testimport-hg.sh b/exporters/darcs/t/testimport-hg.sh new file mode 100644 index 0000000..0a60b8c --- /dev/null +++ b/exporters/darcs/t/testimport-hg.sh @@ -0,0 +1,16 @@ +. lib.sh + +create_hg test + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +(cd test; $pypath/bzrlib/plugins/fastimport/exporters/hg-fast-export.py -r .) | (cd test.darcs; darcs-fast-import) +rm test/{*.orig,hg-export.status} +if [ $? != 0 ]; then + exit 1 +fi +diff_importhg test +exit $? diff --git a/exporters/darcs/t/testimport-rename.sh b/exporters/darcs/t/testimport-rename.sh new file mode 100644 index 0000000..1008bf8 --- /dev/null +++ b/exporters/darcs/t/testimport-rename.sh @@ -0,0 +1,25 @@ +. lib.sh + +rm -rf test +mkdir test +cd test +git init +echo a > file +git add file +git commit -m a1 +git mv file file2 +git commit -m b +cd .. + +rm -rf test.darcs +mkdir test.darcs +cd test.darcs +darcs init +cd .. +(cd test; git fast-export -M HEAD) > out +cat out | (cd test.darcs; darcs-fast-import) +if [ $? != 0 ]; then + exit 1 +fi +diff_importgit test +exit $? diff --git a/exporters/darcs/x2d b/exporters/darcs/x2d new file mode 100755 index 0000000..0344e13 --- /dev/null +++ b/exporters/darcs/x2d @@ -0,0 +1,121 @@ +#!/bin/sh +# +# x2d - convert git, bzr or hg repos to darcs using fast-export +# +# Copyright (c) 2008 by Miklos Vajna <vmiklos@frugalware.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +usage() +{ + echo "Usage: x2d -f format repo" +} + +die() +{ + echo "$@" + usage + exit 1 +} + +check_up_to_date() +{ + upstreamnum=$(darcs show repo|grep 'Num Patches'|sed 's/.*: //') + if [ "$upstreamnum" = "$(cd $origin; eval $*)" ]; then + echo "No remote changes to pull!" + exit 0 + fi +} + +case $1 in + -h|--help) + usage + exit 0 + ;; + -f) + format="$2" + shift 2 + ;; +esac + +[ -n "$format" ] || die "Source format is not given!" + +case $format in + git|bzr|hg) + ;; + *) + die "The requested source format is not yet supported!" + ;; +esac + +origin="$1" +shift 1 + +[ -d "$origin" ] || die "Source repo does not exist!" + +# convert to abspath +cd $origin +origin=$(pwd) + +dmark="$origin.darcs/_darcs/fast-import/dfe-marks" +fmark="$origin.darcs/_darcs/fast-import/ffi-marks" + +mkdir -p $origin.darcs +cd $origin.darcs + +common_opts="--logfile $origin.darcs/_darcs/fast-import/log" +pypath="/$(python -c 'from distutils import sysconfig; print sysconfig.get_python_lib()[1:]')/" + +if [ ! -f $dmark ]; then + darcs init + mkdir -p _darcs/fast-import + case $format in + git) + (cd $origin; git fast-export --export-marks=$fmark HEAD) | \ + darcs-fast-import --export-marks=$dmark $common_opts + ;; + bzr) + (cd $origin; bzr fast-export \ + --export-marks=$fmark . ) | darcs-fast-import --export-marks=$dmark $common_opts + ;; + hg) + (cd $origin; $pypath/bzrlib/plugins/fastimport/exporters/hg-fast-export.py -r . ) | \ + darcs-fast-import --export-marks=$dmark $common_opts + esac +else + case $format in + git) + check_up_to_date "git rev-list HEAD |wc -l" + (cd $origin; git fast-export --export-marks=$fmark --import-marks=$fmark HEAD) | \ + darcs-fast-import --export-marks=$dmark --import-marks=$dmark $common_opts + ;; + bzr) + # bzr revno is not good here, because at merges + # it produces less revision than the number we + # have in darcs + check_up_to_date "bzr log|grep -c revno:" + (cd $origin; bzr fast-export \ + --export-marks=$fmark --import-marks=$fmark . ) | \ + darcs-fast-import --export-marks=$dmark --import-marks=$dmark $common_opts + ;; + hg) + check_up_to_date 'echo $(($(hg tip --template "{rev}")+1))' + (cd $origin; $pypath/bzrlib/plugins/fastimport/exporters/hg-fast-export.py -r . ) | \ + darcs-fast-import --export-marks=$dmark --import-marks=$dmark $common_opts + ;; + esac +fi diff --git a/exporters/darcs/x2d.txt b/exporters/darcs/x2d.txt new file mode 100644 index 0000000..eb2ec34 --- /dev/null +++ b/exporters/darcs/x2d.txt @@ -0,0 +1,26 @@ += x2d(1) + +== NAME + +x2d - convert git, bzr or hg repos to a darcs one using fast-export + +== SYNOPSIS + +x2d -f <format> <otherrepo> + +== DESCRIPTION + +x2d is a wrapper script that just automates doing an initial or +continuing an incremental conversion. All it does is initializing the +target darcs repo, starting darcs-fast-import and the relevant exporter +with the proper switches and pipe the importer's output to the +importer's standard input. + +== OPTIONS + +--help:: + Display usage. + +-f <format>:: + Specify the format of the source repo. Currently supported sources are + git, bzr and hg. Incremental conversion is supported for all of them. |