[PATCH 4/4] strbuf_split*(): document functions

2012-11-03 Thread Michael Haggerty
Document strbuf_split_buf(), strbuf_split_str(), strbuf_split_max(),
strbuf_split(), and strbuf_list_free() in the header file and in
api-strbuf.txt.  (These functions were previously completely
undocumented.)

Signed-off-by: Michael Haggerty 
---
 Documentation/technical/api-strbuf.txt | 16 
 strbuf.h   | 33 +
 2 files changed, 49 insertions(+)

diff --git a/Documentation/technical/api-strbuf.txt 
b/Documentation/technical/api-strbuf.txt
index 95a8bf3..84686b5 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -279,6 +279,22 @@ same behaviour as well.
Strip whitespace from a buffer. The second parameter controls if
comments are considered contents to be removed or not.
 
+`strbuf_split_buf`::
+`strbuf_split_str`::
+`strbuf_split_max`::
+`strbuf_split`::
+
+   Split a string or strbuf into a list of strbufs at a specified
+   terminator character.  The returned substrings include the
+   terminator characters.  Some of these functions take a `max`
+   parameter, which, if positive, limits the output to that
+   number of substrings.
+
+`strbuf_list_free`::
+
+   Free a list of strbufs (for example, the return values of the
+   `strbuf_split()` functions).
+
 `launch_editor`::
 
Launch the user preferred editor to edit a file and fill the buffer
diff --git a/strbuf.h b/strbuf.h
index c896a47..aa386c6 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -44,23 +44,56 @@ extern void strbuf_rtrim(struct strbuf *);
 extern void strbuf_ltrim(struct strbuf *);
 extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
 
+/*
+ * Split str (of length slen) at the specified terminator character.
+ * Return a null-terminated array of pointers to strbuf objects
+ * holding the substrings.  The substrings include the terminator,
+ * except for the last substring, which might be unterminated if the
+ * original string did not end with a terminator.  If max is positive,
+ * then split the string into at most max substrings (with the last
+ * substring containing everything following the (max-1)th terminator
+ * character).
+ *
+ * For lighter-weight alternatives, see string_list_split() and
+ * string_list_split_in_place().
+ */
 extern struct strbuf **strbuf_split_buf(const char *, size_t,
int terminator, int max);
+
+/*
+ * Split a NUL-terminated string at the specified terminator
+ * character.  See strbuf_split_buf() for more information.
+ */
 static inline struct strbuf **strbuf_split_str(const char *str,
   int terminator, int max)
 {
return strbuf_split_buf(str, strlen(str), terminator, max);
 }
+
+/*
+ * Split a strbuf at the specified terminator character.  See
+ * strbuf_split_buf() for more information.
+ */
 static inline struct strbuf **strbuf_split_max(const struct strbuf *sb,
int terminator, int max)
 {
return strbuf_split_buf(sb->buf, sb->len, terminator, max);
 }
+
+/*
+ * Split a strbuf at the specified terminator character.  See
+ * strbuf_split_buf() for more information.
+ */
 static inline struct strbuf **strbuf_split(const struct strbuf *sb,
   int terminator)
 {
return strbuf_split_max(sb, terminator, 0);
 }
+
+/*
+ * Free a NULL-terminated list of strbufs (for example, the return
+ * values of the strbuf_split*() functions).
+ */
 extern void strbuf_list_free(struct strbuf **);
 
 /*- add data in your buffer -*/
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/4] strbuf_split_buf(): simplify iteration

2012-11-03 Thread Michael Haggerty
While iterating, update str and slen to keep track of the part of the
string that hasn't been processed yet rather than computing things
relative to the start of the original string.  This eliminates one
local variable, reduces the scope of another, and reduces the amount
of arithmetic needed within the loop.

Signed-off-by: Michael Haggerty 
---
 strbuf.c | 23 ++-
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index 5256c2a..c7cd529 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -110,25 +110,22 @@ struct strbuf **strbuf_split_buf(const char *str, size_t 
slen, int delim, int ma
 {
struct strbuf **ret = NULL;
size_t nr = 0, alloc = 0;
-   const char *n, *p;
struct strbuf *t;
 
-   p = n = str;
-   while (n < str + slen) {
-   int len;
-   if (max <= 0 || nr + 1 < max)
-   n = memchr(n, delim, slen - (n - str));
-   else
-   n = NULL;
-   if (!n)
-   n = str + slen - 1;
-   len = n - p + 1;
+   while (slen) {
+   int len = slen;
+   if (max <= 0 || nr + 1 < max) {
+   const char *end = memchr(str, delim, slen);
+   if (end)
+   len = end - str + 1;
+   }
t = xmalloc(sizeof(struct strbuf));
strbuf_init(t, len);
-   strbuf_add(t, p, len);
+   strbuf_add(t, str, len);
ALLOC_GROW(ret, nr + 2, alloc);
ret[nr++] = t;
-   p = ++n;
+   str += len;
+   slen -= len;
}
ALLOC_GROW(ret, nr + 1, alloc); /* In case string was empty */
ret[nr] = NULL;
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/4] strbuf_split*(): rename "delim" parameter to "terminator"

2012-11-03 Thread Michael Haggerty
The word "delimiter" suggests that the argument separates the
substrings, whereas in fact (1) the delimiter characters are included
in the output, and (2) if the input string ends with the delimiter,
then the output does not include a final empty string.  So rename the
"delim" arguments of the strbuf_split() family of functions to
"terminator", which is more suggestive of how it is used.

Signed-off-by: Michael Haggerty 
---
 strbuf.c |  5 +++--
 strbuf.h | 15 ---
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index c7cd529..05d0693 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -106,7 +106,8 @@ void strbuf_ltrim(struct strbuf *sb)
sb->buf[sb->len] = '\0';
 }
 
-struct strbuf **strbuf_split_buf(const char *str, size_t slen, int delim, int 
max)
+struct strbuf **strbuf_split_buf(const char *str, size_t slen,
+int terminator, int max)
 {
struct strbuf **ret = NULL;
size_t nr = 0, alloc = 0;
@@ -115,7 +116,7 @@ struct strbuf **strbuf_split_buf(const char *str, size_t 
slen, int delim, int ma
while (slen) {
int len = slen;
if (max <= 0 || nr + 1 < max) {
-   const char *end = memchr(str, delim, slen);
+   const char *end = memchr(str, terminator, slen);
if (end)
len = end - str + 1;
}
diff --git a/strbuf.h b/strbuf.h
index be941ee..c896a47 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -45,20 +45,21 @@ extern void strbuf_ltrim(struct strbuf *);
 extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
 
 extern struct strbuf **strbuf_split_buf(const char *, size_t,
-   int delim, int max);
+   int terminator, int max);
 static inline struct strbuf **strbuf_split_str(const char *str,
-  int delim, int max)
+  int terminator, int max)
 {
-   return strbuf_split_buf(str, strlen(str), delim, max);
+   return strbuf_split_buf(str, strlen(str), terminator, max);
 }
 static inline struct strbuf **strbuf_split_max(const struct strbuf *sb,
-   int delim, int max)
+   int terminator, int max)
 {
-   return strbuf_split_buf(sb->buf, sb->len, delim, max);
+   return strbuf_split_buf(sb->buf, sb->len, terminator, max);
 }
-static inline struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
+static inline struct strbuf **strbuf_split(const struct strbuf *sb,
+  int terminator)
 {
-   return strbuf_split_max(sb, delim, 0);
+   return strbuf_split_max(sb, terminator, 0);
 }
 extern void strbuf_list_free(struct strbuf **);
 
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] strbuf_split_buf(): use ALLOC_GROW()

2012-11-03 Thread Michael Haggerty
Use ALLOC_GROW() rather than inline code to manage memory in
strbuf_split_buf().  Rename "pos" to "nr" because it better describes
the use of the variable and it better conforms to the "ALLOC_GROW"
idiom.

Also, instead of adding a sentinal NULL value after each entry is
added to the list, only add it once after all of the entries have been
added.

Signed-off-by: Michael Haggerty 
---
 strbuf.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index 4b9e30c..5256c2a 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -108,33 +108,30 @@ void strbuf_ltrim(struct strbuf *sb)
 
 struct strbuf **strbuf_split_buf(const char *str, size_t slen, int delim, int 
max)
 {
-   int alloc = 2, pos = 0;
+   struct strbuf **ret = NULL;
+   size_t nr = 0, alloc = 0;
const char *n, *p;
-   struct strbuf **ret;
struct strbuf *t;
 
-   ret = xcalloc(alloc, sizeof(struct strbuf *));
p = n = str;
while (n < str + slen) {
int len;
-   if (max <= 0 || pos + 1 < max)
+   if (max <= 0 || nr + 1 < max)
n = memchr(n, delim, slen - (n - str));
else
n = NULL;
-   if (pos + 1 >= alloc) {
-   alloc = alloc * 2;
-   ret = xrealloc(ret, sizeof(struct strbuf *) * alloc);
-   }
if (!n)
n = str + slen - 1;
len = n - p + 1;
t = xmalloc(sizeof(struct strbuf));
strbuf_init(t, len);
strbuf_add(t, p, len);
-   ret[pos] = t;
-   ret[++pos] = NULL;
+   ALLOC_GROW(ret, nr + 2, alloc);
+   ret[nr++] = t;
p = ++n;
}
+   ALLOC_GROW(ret, nr + 1, alloc); /* In case string was empty */
+   ret[nr] = NULL;
return ret;
 }
 
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/4] Simplify and document strbuf_split() functions

2012-11-03 Thread Michael Haggerty
The strbuf_split() family of functions was completely undocumented.
Add documentation and also simplify the definition of
strbuf_split_buf().

Michael Haggerty (4):
  strbuf_split_buf(): use ALLOC_GROW()
  strbuf_split_buf(): simplify iteration
  strbuf_split*(): rename "delim" parameter to "terminator"
  strbuf_split*(): document functions

 Documentation/technical/api-strbuf.txt | 16 
 strbuf.c   | 39 ---
 strbuf.h   | 48 +-
 3 files changed, 74 insertions(+), 29 deletions(-)

-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 00/13] New remote-hg helper

2012-11-03 Thread Felipe Contreras
On Fri, Nov 2, 2012 at 8:20 PM, Felipe Contreras
 wrote:
> On Fri, Nov 2, 2012 at 7:39 PM, Felipe Contreras
>  wrote:
>
>> As a rule, I don't see much value in writing a framework that works
>> only for one case, that smells more like over-engineering. If we had
>> two cases (hg and bzr), then we might be able to know with a modicum
>> of certainty what such a framework should have. So I would prefer to
>> have two standalone remote-helpers, and _then_ do a framework to
>> simplify both, but not before. But that's my personal opinion.
>>
>> Now that I have free time, I might be able to spend time writing such
>> a proof-of-concept remote-bzr, and a simple framework. But I would be
>> concentrated on remote-hg.
>
> Actually, there's no point in that; there's already a git-remote-bzr:
>
> http://bazaar.launchpad.net/~bzr-git/bzr-git/trunk/view/head:/git-remote-bzr

Turns out the quality of that tools is not that great, so I decided to
write a simple one using bzr-fastimport. It works nicely, although I
wouldn't trust the quality of bzr-fastimport too much.

It's so simple I don't see the need of a framework, but if needed, one
could be done taking these git-remote-{hg,bzr} as a basis.

Cheers.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] remote-bzr: add simple tests

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/test-bzr.sh | 111 +
 1 file changed, 111 insertions(+)
 create mode 100755 contrib/remote-helpers/test-bzr.sh

diff --git a/contrib/remote-helpers/test-bzr.sh 
b/contrib/remote-helpers/test-bzr.sh
new file mode 100755
index 000..8594ffc
--- /dev/null
+++ b/contrib/remote-helpers/test-bzr.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+test_description='Test remote-bzr'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+   skip_all='skipping remote-bzr tests; python not available'
+   test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import bzrlib'; then
+   skip_all='skipping remote-bzr tests; bzr not available'
+   test_done
+fi
+
+cmd=<&2
+   skip_all='skipping remote-bzr tests; bzr-fastimport not available'
+   test_done
+fi
+
+check () {
+   (cd $1 &&
+   git log --format='%s' -1 &&
+   git symbolic-ref HEAD) > actual &&
+   (echo $2 &&
+   echo "refs/heads/$3") > expected &&
+   test_cmp expected actual
+}
+
+bzr whoami "A U Thor "
+
+test_expect_success 'cloning' '
+  (bzr init bzrrepo &&
+  cd bzrrepo &&
+  echo one > content &&
+  bzr add content &&
+  bzr commit -m one
+  ) &&
+
+  git clone "bzr::$PWD/bzrrepo" gitrepo &&
+  check gitrepo one master
+'
+
+test_expect_success 'pulling' '
+  (cd bzrrepo &&
+  echo two > content &&
+  bzr commit -m two
+  ) &&
+
+  (cd gitrepo && git pull) &&
+
+  check gitrepo two master
+'
+
+test_expect_success 'pushing' '
+  (cd gitrepo &&
+  echo three > content &&
+  git commit -a -m three &&
+  git push
+  ) &&
+
+  echo three > expected &&
+  cat bzrrepo/content > actual &&
+  test_cmp expected actual
+'
+
+test_expect_success 'roundtrip' '
+  (cd gitrepo &&
+  git pull &&
+  git log --format="%s" -1 origin/master > actual) &&
+  echo three > expected &&
+  test_cmp expected actual &&
+
+  (cd gitrepo && git push && git pull) &&
+
+  (cd bzrrepo &&
+  echo four > content &&
+  bzr commit -m four
+  ) &&
+
+  (cd gitrepo && git pull && git push) &&
+
+  check gitrepo four master &&
+
+  (cd gitrepo &&
+  echo five > content &&
+  git commit -a -m five &&
+  git push && git pull
+  ) &&
+
+  (cd bzrrepo && bzr revert) &&
+
+  echo five > expected &&
+  cat bzrrepo/content > actual &&
+  test_cmp expected actual
+'
+
+test_done
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] remote-bzr: add support for pushing

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-bzr | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/contrib/remote-helpers/git-remote-bzr 
b/contrib/remote-helpers/git-remote-bzr
index 76a609a..de37217 100755
--- a/contrib/remote-helpers/git-remote-bzr
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -26,6 +26,9 @@ bzrlib.plugin.load_plugins()
 import bzrlib.revisionspec
 
 from bzrlib.plugins.fastimport import exporter as bzr_exporter
+from bzrlib.plugins.fastimport.processors import generic_processor as 
bzr_generic_processor
+
+import fastimport.parser
 
 import sys
 import os
@@ -140,9 +143,38 @@ def do_import(parser):
 
 sys.stdout.flush()
 
+def do_export(parser):
+global dirname
+
+parser.next() # can't handle 'done'?
+
+controldir = parser.repo.bzrdir
+
+path = os.path.join(dirname, 'marks-bzr')
+params = { 'import-marks': path, 'export-marks': path }
+
+proc = bzr_generic_processor.GenericProcessor(controldir, params)
+p = fastimport.parser.ImportParser(sys.stdin)
+proc.process(p.iter_commands)
+
+if parser.repo.last_revision() != marks.get_tip('master'):
+print 'ok %s' % 'refs/heads/master'
+
+print
+
 def do_capabilities(parser):
+global dirname
+
 print "import"
+print "export"
 print "refspec refs/heads/*:%s/heads/*" % prefix
+
+path = os.path.join(dirname, 'marks-git')
+
+if os.path.exists(path):
+print "*import-marks %s" % path
+print "*export-marks %s" % path
+
 print
 
 def do_list(parser):
@@ -178,6 +210,8 @@ def main(args):
 do_list(parser)
 elif parser.check('import'):
 do_import(parser)
+elif parser.check('export'):
+do_export(parser)
 else:
 die('unhandled command: %s' % line)
 sys.stdout.flush()
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] Add new remote-bzr transport helper

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-bzr | 187 ++
 1 file changed, 187 insertions(+)
 create mode 100755 contrib/remote-helpers/git-remote-bzr

diff --git a/contrib/remote-helpers/git-remote-bzr 
b/contrib/remote-helpers/git-remote-bzr
new file mode 100755
index 000..76a609a
--- /dev/null
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# git clone bzr::/path/to/mercurial/repo/
+#
+# You need to have bzr-fastimport installed:
+# http://wiki.bazaar.canonical.com/BzrFastImport
+#
+# You might also need to find this line bzr-fastimport's
+# code, and modify it:
+#
+# self._use_known_graph = False
+
+import sys
+
+import bzrlib
+bzrlib.initialize()
+
+import bzrlib.plugin
+bzrlib.plugin.load_plugins()
+
+import bzrlib.revisionspec
+
+from bzrlib.plugins.fastimport import exporter as bzr_exporter
+
+import sys
+import os
+import json
+
+def die(msg, *args):
+sys.stderr.write('ERROR: %s\n' % (msg % args))
+sys.exit(1)
+
+def warn(msg, *args):
+sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+class Marks:
+
+def __init__(self, path):
+self.path = path
+self.tips = {}
+self.load()
+
+def load(self):
+if not os.path.exists(self.path):
+return
+
+tmp = json.load(open(self.path))
+self.tips = tmp['tips']
+
+def dict(self):
+return { 'tips': self.tips }
+
+def store(self):
+json.dump(self.dict(), open(self.path, 'w'))
+
+def __str__(self):
+return str(self.dict())
+
+def get_tip(self, branch):
+return self.tips.get(branch, '1')
+
+def set_tip(self, branch, tip):
+self.tips[branch] = tip
+
+class Parser:
+
+def __init__(self, repo):
+self.repo = repo
+self.line = self.get_line()
+
+def get_line(self):
+return sys.stdin.readline().strip()
+
+def __getitem__(self, i):
+return self.line.split()[i]
+
+def check(self, word):
+return self.line.startswith(word)
+
+def each_block(self, separator):
+while self.line != separator:
+yield self.line
+self.line = self.get_line()
+
+def __iter__(self):
+return self.each_block('')
+
+def next(self):
+self.line = self.get_line()
+if self.line == 'done':
+self.line = None
+
+def export_branch(branch, name):
+global prefix, dirname
+
+marks_path = os.path.join(dirname, 'marks-bzr')
+ref = '%s/heads/%s' % (prefix, name)
+tip = marks.get_tip(name)
+start = "before:%s" % tip
+rev1 = bzrlib.revisionspec.RevisionSpec.from_string(start)
+rev2 = bzrlib.revisionspec.RevisionSpec.from_string(None)
+
+exporter = bzr_exporter.BzrFastExporter(branch,
+outf=sys.stdout, ref=ref,
+checkpoint=None,
+import_marks_file=marks_path,
+export_marks_file=marks_path,
+revision=[rev1, rev2],
+verbose=None, plain_format=True,
+rewrite_tags=False)
+exporter.run()
+
+marks.set_tip(name, branch.last_revision())
+
+def do_import(parser):
+global dirname
+
+branch = parser.repo
+path = os.path.join(dirname, 'marks-git')
+
+print "feature done"
+if os.path.exists(path):
+print "feature import-marks=%s" % path
+print "feature export-marks=%s" % path
+sys.stdout.flush()
+
+while parser.check('import'):
+ref = parser[1]
+if ref.startswith('refs/heads/'):
+name = ref[len('refs/heads/'):]
+export_branch(branch, name)
+parser.next()
+
+print 'done'
+
+sys.stdout.flush()
+
+def do_capabilities(parser):
+print "import"
+print "refspec refs/heads/*:%s/heads/*" % prefix
+print
+
+def do_list(parser):
+print "? refs/heads/%s" % 'master'
+print "@refs/heads/%s HEAD" % 'master'
+print
+
+def main(args):
+global marks, prefix, dirname
+
+alias = args[1]
+url = args[2]
+
+d = bzrlib.controldir.ControlDir.open(url)
+repo = d.open_branch()
+
+prefix = 'refs/bzr/%s' % alias
+
+gitdir = os.environ['GIT_DIR']
+dirname = os.path.join(gitdir, 'bzr', alias)
+
+if not os.path.exists(dirname):
+os.makedirs(dirname)
+
+marks_path = os.path.join(dirname, 'marks-int')
+marks = Marks(marks_path)
+
+parser = Parser(repo)
+for line in parser:
+if parser.check('capabilities'):
+do_capabilities(parser)
+elif parser.check('list'):
+do_list(parser)
+elif parser.check('import'):
+do_import(parser)
+else:
+die('unhandled command: %s' % line)
+sys.stdout.flush()
+
+marks.store()
+
+sys.exit(main(sys.argv))
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the

[PATCH 0/3] New remote-bzr remote helper

2012-11-03 Thread Felipe Contreras
Hi,

This is a proof-of-concept remote helper for bzr, that turns out to work rather 
well.

It uses bzr-fastimport[1], which is what most current bzr<->git tools uses, but
the quality is not that great. After applying an important fix[2], it works
nicely, but you will get tons of verbose messages.

Eventually we might want to implement the same functionality as bzr-fastimport,
but for now this already works nicely enough.

Cheers.

[1] http://wiki.bazaar.canonical.com/BzrFastImport
[2] https://launchpadlibrarian.net/121967844/bzr-fastimport-no-graph.patch

Felipe Contreras (3):
  Add new remote-bzr transport helper
  remote-bzr: add support for pushing
  remote-bzr: add simple tests

 contrib/remote-helpers/git-remote-bzr | 221 ++
 contrib/remote-helpers/test-bzr.sh| 111 +
 2 files changed, 332 insertions(+)
 create mode 100755 contrib/remote-helpers/git-remote-bzr
 create mode 100755 contrib/remote-helpers/test-bzr.sh

-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 16/16] remote-hg: the author email can be null

2012-11-03 Thread Felipe Contreras
Like 'Foo <>'.

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index a9ae844..7929eec 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -35,9 +35,9 @@ import urllib
 #
 
 NAME_RE = re.compile('^([^<>]+)')
-AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
-AUTHOR_HG_RE = re.compile('^(.*?) ?<(.+?)(?:>(.+)?)?$')
-RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')
+AUTHOR_HG_RE = re.compile('^(.*?) ?<(.*?)(?:>(.+)?)?$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
 sys.stderr.write('ERROR: %s\n' % (msg % args))
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 15/16] remote-hg: add option to not track branches

2012-11-03 Thread Felipe Contreras
Some people prefer it this way.

 % git config --global remote-hg.track-branches false

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index dbe309a..a9ae844 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -449,14 +449,9 @@ def list_head(repo, cur):
 g_head = (head, node)
 
 def do_list(parser):
-global branches, bmarks, mode
+global branches, bmarks, mode, track_branches
 
 repo = parser.repo
-for branch in repo.branchmap():
-heads = repo.branchheads(branch)
-if len(heads):
-branches[branch] = heads
-
 for bmark, node in bookmarks.listbookmarks(repo).iteritems():
 bmarks[bmark] = repo[node]
 
@@ -464,7 +459,12 @@ def do_list(parser):
 
 list_head(repo, cur)
 
-if mode != 'hg':
+if track_branches:
+for branch in repo.branchmap():
+heads = repo.branchheads(branch)
+if len(heads):
+branches[branch] = heads
+
 for branch in branches:
 print "? refs/heads/branches/%s" % branch
 
@@ -713,16 +713,22 @@ def main(args):
 global prefix, dirname, branches, bmarks
 global marks, blob_marks, parsed_refs
 global peer, mode, bad_mail, bad_name
+global track_branches
 
 alias = args[1]
 url = args[2]
 peer = None
 
-cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
 hg_git_compat = False
+track_branches = True
 try:
+cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
 if subprocess.check_output(cmd) == 'true\n':
 hg_git_compat = True
+track_branches = False
+cmd = ['git', 'config', '--get', 'remote-hg.track-branches']
+if subprocess.check_output(cmd) == 'false\n':
+track_branches = False
 except subprocess.CalledProcessError:
 pass
 
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 14/16] remote-hg: add extra author test

2012-11-03 Thread Felipe Contreras
For hg.hg.

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/test-hg-hg-git.sh | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/contrib/remote-helpers/test-hg-hg-git.sh 
b/contrib/remote-helpers/test-hg-hg-git.sh
index e07bba5..3e76d9f 100755
--- a/contrib/remote-helpers/test-hg-hg-git.sh
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -370,7 +370,11 @@ test_expect_success 'hg author' '
 
echo theta > theta &&
hg add theta &&
-   hg commit -u "test >t...@example.com>" -m "add theta"
+   hg commit -u "test >t...@example.com>" -m "add theta" &&
+
+   echo iota > iota &&
+   hg add iota &&
+   hg commit -u "test  example  com>" -m "add iota"
) &&
 
hg_push_$x hgrepo-$x gitrepo-$x &&
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 13/16] remote-hg: add tests to compare with hg-git

2012-11-03 Thread Felipe Contreras
The base commands come from the tests of the hg-git project.

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/test-hg-hg-git.sh | 462 +++
 1 file changed, 462 insertions(+)
 create mode 100755 contrib/remote-helpers/test-hg-hg-git.sh

diff --git a/contrib/remote-helpers/test-hg-hg-git.sh 
b/contrib/remote-helpers/test-hg-hg-git.sh
new file mode 100755
index 000..e07bba5
--- /dev/null
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -0,0 +1,462 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test remote-hg output compared to hg-git'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+   skip_all='skipping remote-hg tests; python not available'
+   test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+   skip_all='skipping remote-hg tests; mercurial not available'
+   test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import hggit'; then
+   skip_all='skipping remote-hg tests; hg-git not available'
+   test_done
+fi
+
+# clone to a git repo with git
+git_clone_git () {
+   hg -R $1 bookmark -f -r tip master &&
+   git clone -q "hg::$PWD/$1" $2
+}
+
+# clone to an hg repo with git
+hg_clone_git () {
+   (
+   hg init $2 &&
+   cd $1 &&
+   git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 
'refs/heads/*:refs/heads/*'
+   ) &&
+
+   (cd $2 && hg -q update)
+}
+
+# clone to a git repo with hg
+git_clone_hg () {
+   (
+   git init -q $2 &&
+   cd $1 &&
+   hg bookmark -f -r tip master &&
+   hg -q push -r master ../$2 || true
+   )
+}
+
+# clone to an hg repo with hg
+hg_clone_hg () {
+   hg -q clone $1 $2
+}
+
+# push an hg repo with git
+hg_push_git () {
+   (
+   cd $2
+   old=$(git symbolic-ref --short HEAD)
+   git checkout -q -b tmp &&
+   git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 
'refs/heads/*:refs/heads/*' &&
+   git checkout -q $old &&
+   git branch -q -D tmp 2> /dev/null || true
+   )
+}
+
+# push an hg git repo with hg
+hg_push_hg () {
+   (
+   cd $1 &&
+   hg -q push ../$2 || true
+   )
+}
+
+hg_log () {
+   hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+}
+
+git_log () {
+   git --git-dir=$1/.git fast-export --branches
+}
+
+setup () {
+   (
+   echo "[ui]"
+   echo "username = A U Thor "
+   echo "[defaults]"
+   echo "backout = -d \"0 0\""
+   echo "commit = -d \"0 0\""
+   echo "debugrawcommit = -d \"0 0\""
+   echo "tag = -d \"0 0\""
+   echo "[extensions]"
+   echo "hgext.bookmarks ="
+   echo "hggit ="
+   ) >> "$HOME"/.hgrc &&
+   git config --global receive.denycurrentbranch warn
+   git config --global remote-hg.hg-git-compat true
+
+   export HGEDITOR=/usr/bin/true
+
+   export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
+   export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+}
+
+setup
+
+test_expect_success 'merge conflict 1' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   hg init hgrepo1 &&
+   cd hgrepo1 &&
+   echo A > afile &&
+   hg add afile &&
+   hg ci -m "origin" &&
+
+   echo B > afile &&
+   hg ci -m "A->B" &&
+
+   hg up -r0 &&
+   echo C > afile &&
+   hg ci -m "A->C" &&
+
+   hg merge -r1 || true &&
+   echo C > afile &&
+   hg resolve -m afile &&
+   hg ci -m "merge to C"
+   ) &&
+
+   for x in hg git; do
+   git_clone_$x hgrepo1 gitrepo-$x &&
+   hg_clone_$x gitrepo-$x hgrepo2-$x &&
+   hg_log hgrepo2-$x > hg-log-$x &&
+   git_log gitrepo-$x > git-log-$x
+   done &&
+
+   test_cmp hg-log-hg hg-log-git &&
+   test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'merge conflict 2' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   hg init hgrepo1 &&
+   cd hgrepo1 &&
+   echo A > afile &&
+   hg add afile &&
+   hg ci -m "origin" &&
+
+   echo B > afile &&
+   hg ci -m "A->B" &&
+
+   hg up -r0 &&
+   echo C > afile &&
+   hg ci -m "A->C" &&
+
+   hg merge -r1 || true &&
+   echo B > afile &&
+   hg resolve -m afile &&
+   hg ci -m "merge to B"
+   ) &&
+
+   for x in hg git; do
+   git_clone_$x hgrepo1 gitrepo-$x &&
+   hg_clone_$x gitrepo-$x hgrepo2-$x &&
+   hg_log hgrepo2-$x > hg-log-$x &&
+   git_log gitrepo-$x > git-log-$x
+   done &&
+
+   test_cmp hg-log-hg hg-log-git &&
+   test_cmp git-log-hg git-log-git
+'
+
+test_expect_success 'converged merge' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   hg init hgrepo1 &&
+   cd hgrepo1 &&
+   echo A > af

[PATCH v6 11/16] test-lib: avoid full path to store test results

2012-11-03 Thread Felipe Contreras
No reason to use the full path in case this is used externally.

Otherwise we might get errors such as:

./test-lib.sh: line 394: 
/home/bob/dev/git/t/test-results//home/bob/dev/git/contrib/remote-hg/test-2894.counts:
 No such file or directory

Signed-off-by: Felipe Contreras 
---
 t/test-lib.sh | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index 514282c..5a3d665 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -389,7 +389,8 @@ test_done () {
then
test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
mkdir -p "$test_results_dir"
-   test_results_path="$test_results_dir/${0%.sh}-$$.counts"
+   base=${0##*/}
+   test_results_path="$test_results_dir/${base%.sh}-$$.counts"
 
cat >>"$test_results_path" <<-EOF
total $test_count
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 12/16] remote-hg: add bidirectional tests

2012-11-03 Thread Felipe Contreras
Base commands from hg-git tests:
https://bitbucket.org/durin42/hg-git/src

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/test-hg-bidi.sh | 243 +
 1 file changed, 243 insertions(+)
 create mode 100755 contrib/remote-helpers/test-hg-bidi.sh

diff --git a/contrib/remote-helpers/test-hg-bidi.sh 
b/contrib/remote-helpers/test-hg-bidi.sh
new file mode 100755
index 000..a94eb28
--- /dev/null
+++ b/contrib/remote-helpers/test-hg-bidi.sh
@@ -0,0 +1,243 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test biridectionality of remote-hg'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+   skip_all='skipping remote-hg tests; python not available'
+   test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+   skip_all='skipping remote-hg tests; mercurial not available'
+   test_done
+fi
+
+# clone to a git repo
+git_clone () {
+   hg -R $1 bookmark -f -r tip master &&
+   git clone -q "hg::$PWD/$1" $2
+}
+
+# clone to an hg repo
+hg_clone () {
+   (
+   hg init $2 &&
+   cd $1 &&
+   git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 
'refs/heads/*:refs/heads/*'
+   ) &&
+
+   (cd $2 && hg -q update)
+}
+
+# push an hg repo
+hg_push () {
+   (
+   cd $2
+   old=$(git symbolic-ref --short HEAD)
+   git checkout -q -b tmp &&
+   git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 
'refs/heads/*:refs/heads/*' &&
+   git checkout -q $old &&
+   git branch -q -D tmp 2> /dev/null || true
+   )
+}
+
+hg_log () {
+   hg -R $1 log --graph --debug | grep -v 'tag: *default/'
+}
+
+setup () {
+   (
+   echo "[ui]"
+   echo "username = A U Thor "
+   echo "[defaults]"
+   echo "backout = -d \"0 0\""
+   echo "commit = -d \"0 0\""
+   echo "debugrawcommit = -d \"0 0\""
+   echo "tag = -d \"0 0\""
+   ) >> "$HOME"/.hgrc &&
+   git config --global remote-hg.hg-git-compat true
+
+   export HGEDITOR=/usr/bin/true
+
+   export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
+   export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+}
+
+setup
+
+test_expect_success 'encoding' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   git init -q gitrepo &&
+   cd gitrepo &&
+
+   echo alpha > alpha &&
+   git add alpha &&
+   git commit -m "add älphà" &&
+
+   export GIT_AUTHOR_NAME="tést èncödîng" &&
+   echo beta > beta &&
+   git add beta &&
+   git commit -m "add beta" &&
+
+   echo gamma > gamma &&
+   git add gamma &&
+   git commit -m "add gämmâ" &&
+
+   : TODO git config i18n.commitencoding latin-1 &&
+   echo delta > delta &&
+   git add delta &&
+   git commit -m "add déltà"
+   ) &&
+
+   hg_clone gitrepo hgrepo &&
+   git_clone hgrepo gitrepo2 &&
+   hg_clone gitrepo2 hgrepo2 &&
+
+   HGENCODING=utf-8 hg_log hgrepo > expected &&
+   HGENCODING=utf-8 hg_log hgrepo2 > actual &&
+
+   test_cmp expected actual
+'
+
+test_expect_success 'file removal' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   git init -q gitrepo &&
+   cd gitrepo &&
+   echo alpha > alpha &&
+   git add alpha &&
+   git commit -m "add alpha" &&
+   echo beta > beta &&
+   git add beta &&
+   git commit -m "add beta"
+   mkdir foo &&
+   echo blah > foo/bar &&
+   git add foo &&
+   git commit -m "add foo" &&
+   git rm alpha &&
+   git commit -m "remove alpha" &&
+   git rm foo/bar &&
+   git commit -m "remove foo/bar"
+   ) &&
+
+   hg_clone gitrepo hgrepo &&
+   git_clone hgrepo gitrepo2 &&
+   hg_clone gitrepo2 hgrepo2 &&
+
+   hg_log hgrepo > expected &&
+   hg_log hgrepo2 > actual &&
+
+   test_cmp expected actual
+'
+
+test_expect_success 'git tags' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   git init -q gitrepo &&
+   cd gitrepo &&
+   git config receive.denyCurrentBranch ignore &&
+   echo alpha > alpha &&
+   git add alpha &&
+   git commit -m "add alpha" &&
+   git tag alpha &&
+
+   echo beta > beta &&
+   git add beta &&
+   git commit -m "add beta" &&
+   git tag -a -m "added tag beta" beta
+   ) &&
+
+   hg_clone gitrepo hgrepo &&
+   git_clone hgrepo gitrepo2 &&
+   hg_clone gitrepo2 hgrepo2 &&
+
+   hg_log hgrepo > expected &&
+   hg_log hgrepo2 > actual &&
+
+   test_cmp expected actual
+'
+
+test_expect_success 'hg branch' '
+   mkdir -p tmp && cd tmp &&
+   test_when_finished "cd .. && rm -rf tmp" &&
+
+   (
+   git init -q gitrepo &&
+   cd gitrepo &&
+
+   echo alpha > alpha &&
+   git add a

[PATCH v6 10/16] remote-hg: add basic tests

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/Makefile   |  13 +
 contrib/remote-helpers/test-hg.sh | 112 ++
 2 files changed, 125 insertions(+)
 create mode 100644 contrib/remote-helpers/Makefile
 create mode 100755 contrib/remote-helpers/test-hg.sh

diff --git a/contrib/remote-helpers/Makefile b/contrib/remote-helpers/Makefile
new file mode 100644
index 000..9a76575
--- /dev/null
+++ b/contrib/remote-helpers/Makefile
@@ -0,0 +1,13 @@
+TESTS := $(wildcard test*.sh)
+
+export T := $(addprefix $(CURDIR)/,$(TESTS))
+export MAKE := $(MAKE) -e
+export PATH := $(CURDIR):$(PATH)
+
+test:
+   $(MAKE) -C ../../t $@
+
+$(TESTS):
+   $(MAKE) -C ../../t $(CURDIR)/$@
+
+.PHONY: $(TESTS)
diff --git a/contrib/remote-helpers/test-hg.sh 
b/contrib/remote-helpers/test-hg.sh
new file mode 100755
index 000..40e6e3c
--- /dev/null
+++ b/contrib/remote-helpers/test-hg.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+# Base commands from hg-git tests:
+# https://bitbucket.org/durin42/hg-git/src
+#
+
+test_description='Test remote-hg'
+
+. ./test-lib.sh
+
+if ! test_have_prereq PYTHON; then
+   skip_all='skipping remote-hg tests; python not available'
+   test_done
+fi
+
+if ! "$PYTHON_PATH" -c 'import mercurial'; then
+   skip_all='skipping remote-hg tests; mercurial not available'
+   test_done
+fi
+
+check () {
+   (cd $1 &&
+   git log --format='%s' -1 &&
+   git symbolic-ref HEAD) > actual &&
+   (echo $2 &&
+   echo "refs/heads/$3") > expected &&
+   test_cmp expected actual
+}
+
+test_expect_success 'cloning' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  hg init hgrepo &&
+  cd hgrepo &&
+  echo zero > content &&
+  hg add content &&
+  hg commit -m zero
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo zero master
+'
+
+test_expect_success 'cloning with branches' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg branch next &&
+  echo next > content &&
+  hg commit -m next
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo next next &&
+
+  (cd hgrepo && hg checkout default) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo2 &&
+  check gitrepo2 zero master
+'
+
+test_expect_success 'cloning with bookmarks' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg bookmark feature-a &&
+  echo feature-a > content &&
+  hg commit -m feature-a
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo feature-a feature-a
+'
+
+test_expect_success 'cloning with detached head' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg update -r 0
+  ) &&
+
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  check gitrepo zero master
+'
+
+test_expect_success 'update bookmark' '
+  test_when_finished "rm -rf gitrepo*" &&
+
+  (
+  cd hgrepo &&
+  hg bookmark devel
+  ) &&
+
+  (
+  git clone "hg::$PWD/hgrepo" gitrepo &&
+  cd gitrepo &&
+  git checkout devel &&
+  echo devel > content &&
+  git commit -a -m devel &&
+  git push
+  ) &&
+
+  hg -R hgrepo bookmarks | grep "devel\s\+3:"
+'
+
+test_done
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 09/16] remote-hg: fake bookmark when there's none

2012-11-03 Thread Felipe Contreras
Or at least no current bookmark.

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 9db4b7e..dbe309a 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -26,7 +26,7 @@ import urllib
 # git:
 # Sensible defaults for git.
 # hg bookmarks are exported as git branches, hg branches are prefixed
-# with 'branches/'.
+# with 'branches/', HEAD is a special case.
 #
 # hg:
 # Emulate hg-git.
@@ -430,12 +430,21 @@ def get_branch_tip(repo, branch):
 return heads[0]
 
 def list_head(repo, cur):
-global g_head
+global g_head, bmarks
 
 head = bookmarks.readcurrent(repo)
-if not head:
-return
-node = repo[head]
+if head:
+node = repo[head]
+else:
+# fake bookmark from current branch
+head = cur
+node = repo['.']
+if not node:
+return
+if head == 'default':
+head = 'master'
+bmarks[head] = node
+
 print "@refs/heads/%s HEAD" % head
 g_head = (head, node)
 
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 08/16] remote-hg: add compat for hg-git author fixes

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 59 
 1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index d585756..9db4b7e 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -17,6 +17,7 @@ import os
 import json
 import shutil
 import subprocess
+import urllib
 
 #
 # If you want to switch to hg-git compatibility mode:
@@ -35,6 +36,7 @@ import subprocess
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+AUTHOR_HG_RE = re.compile('^(.*?) ?<(.+?)(?:>(.+)?)?$')
 RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
@@ -152,12 +154,20 @@ class Parser:
 return sys.stdin.read(size)
 
 def get_author(self):
+global bad_mail
+
+ex = None
 m = RAW_AUTHOR_RE.match(self.line)
 if not m:
 return None
 _, name, email, date, tz = m.groups()
+if name and 'ext:' in name:
+m = re.match('^(.+?) ext:\((.+)\)$', name)
+if m:
+name = m.group(1)
+ex = urllib.unquote(m.group(2))
 
-if email != 'unknown':
+if email != bad_mail:
 if name:
 user = '%s <%s>' % (name, email)
 else:
@@ -165,6 +175,9 @@ class Parser:
 else:
 user = name
 
+if ex:
+user += ex
+
 tz = int(tz)
 tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
 return (user, int(date), -tz)
@@ -194,9 +207,9 @@ def get_filechanges(repo, ctx, parent):
 
 return added | modified, removed
 
-def fixup_user(user):
-user = user.replace('"', '')
+def fixup_user_git(user):
 name = mail = None
+user = user.replace('"', '')
 m = AUTHOR_RE.match(user)
 if m:
 name = m.group(1)
@@ -205,11 +218,41 @@ def fixup_user(user):
 m = NAME_RE.match(user)
 if m:
 name = m.group(1).strip()
+return (name, mail)
+
+def fixup_user_hg(user):
+def sanitize(name):
+# stole this from hg-git
+return re.sub('[<>\n]', '?', name.lstrip('< ').rstrip('> '))
+
+m = AUTHOR_HG_RE.match(user)
+if m:
+name = sanitize(m.group(1))
+mail = sanitize(m.group(2))
+ex = m.group(3)
+if ex:
+name += ' ext:(' + urllib.quote(ex) + ')'
+else:
+name = sanitize(user)
+if '@' in user:
+mail = name
+else:
+mail = None
+
+return (name, mail)
+
+def fixup_user(user):
+global mode, bad_mail
+
+if mode == 'git':
+name, mail = fixup_user_git(user)
+else:
+name, mail = fixup_user_hg(user)
 
 if not name:
-name = 'Unknown'
+name = bad_name
 if not mail:
-mail = 'unknown'
+mail = bad_mail
 
 return '%s <%s>' % (name, mail)
 
@@ -660,7 +703,7 @@ def do_export(parser):
 def main(args):
 global prefix, dirname, branches, bmarks
 global marks, blob_marks, parsed_refs
-global peer, mode
+global peer, mode, bad_mail, bad_name
 
 alias = args[1]
 url = args[2]
@@ -676,8 +719,12 @@ def main(args):
 
 if hg_git_compat:
 mode = 'hg'
+bad_mail = 'none@none'
+bad_name = ''
 else:
 mode = 'git'
+bad_mail = 'unknown'
+bad_name = 'Unknown'
 
 if alias[4:] == url:
 is_tmp = True
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 06/16] remote-hg: match hg merge behavior

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 17 +
 1 file changed, 17 insertions(+)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 503a9fc..247b7cb 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -427,6 +427,14 @@ def parse_blob(parser):
 parser.next()
 return
 
+def get_merge_files(repo, p1, p2, files):
+for e in repo[p1].files():
+if e not in files:
+if e not in repo[p1].manifest():
+continue
+f = { 'ctx' : repo[p1][e] }
+files[e] = f
+
 def parse_commit(parser):
 global marks, blob_marks, bmarks, parsed_refs
 
@@ -470,6 +478,8 @@ def parse_commit(parser):
 of = files[f]
 if 'deleted' in of:
 raise IOError
+if 'ctx' in of:
+return of['ctx']
 is_exec = of['mode'] == 'x'
 is_link = of['mode'] == 'l'
 return context.memfilectx(f, of['data'], is_link, is_exec, None)
@@ -492,6 +502,13 @@ def parse_commit(parser):
 else:
 p2 = '\0' * 20
 
+#
+# If files changed from any of the parents, hg wants to know, but in git if
+# nothing changed from the first parent, nothing changed.
+#
+if merge_mark:
+get_merge_files(repo, p1, p2, files)
+
 ctx = context.memctx(repo, (p1, p2), data,
 files.keys(), getfilectx,
 user, (date, tz), extra)
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 07/16] remote-hg: add support for hg-git compat mode

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 89 +---
 1 file changed, 83 insertions(+), 6 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 247b7cb..d585756 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -16,6 +16,22 @@ import sys
 import os
 import json
 import shutil
+import subprocess
+
+#
+# If you want to switch to hg-git compatibility mode:
+# git config --global remote-hg.hg-git-compat true
+#
+# git:
+# Sensible defaults for git.
+# hg bookmarks are exported as git branches, hg branches are prefixed
+# with 'branches/'.
+#
+# hg:
+# Emulate hg-git.
+# Only hg bookmarks are exported as git branches.
+# Commits are modified to preserve hg information and allow biridectionality.
+#
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
@@ -226,7 +242,7 @@ def mark_to_rev(mark):
 return marks.to_rev(mark)
 
 def export_ref(repo, name, kind, head):
-global prefix, marks
+global prefix, marks, mode
 
 ename = '%s/%s' % (kind, name)
 tip = marks.get_tip(ename)
@@ -261,6 +277,33 @@ def export_ref(repo, name, kind, head):
 else:
 modified, removed = get_filechanges(repo, c, parents[0])
 
+if mode == 'hg':
+extra_msg = ''
+
+if rev_branch != 'default':
+extra_msg += 'branch : %s\n' % rev_branch
+
+renames = []
+for f in c.files():
+if f not in c.manifest():
+continue
+rename = c.filectx(f).renamed()
+if rename:
+renames.append((rename[0], f))
+
+for e in renames:
+extra_msg += "rename : %s => %s\n" % e
+
+for key, value in extra.iteritems():
+if key in ('author', 'committer', 'encoding', 'message', 
'branch', 'hg-git'):
+continue
+else:
+extra_msg += "extra : %s : %s\n" % (key, 
urllib.quote(value))
+
+desc += '\n'
+if extra_msg:
+desc += '\n--HG--\n' + extra_msg
+
 if len(parents) == 0 and rev:
 print 'reset %s/%s' % (prefix, ename)
 
@@ -354,7 +397,7 @@ def list_head(repo, cur):
 g_head = (head, node)
 
 def do_list(parser):
-global branches, bmarks
+global branches, bmarks, mode
 
 repo = parser.repo
 for branch in repo.branchmap():
@@ -368,8 +411,11 @@ def do_list(parser):
 cur = repo.dirstate.branch()
 
 list_head(repo, cur)
-for branch in branches:
-print "? refs/heads/branches/%s" % branch
+
+if mode != 'hg':
+for branch in branches:
+print "? refs/heads/branches/%s" % branch
+
 for bmark in bmarks:
 print "? refs/heads/%s" % bmark
 
@@ -437,6 +483,7 @@ def get_merge_files(repo, p1, p2, files):
 
 def parse_commit(parser):
 global marks, blob_marks, bmarks, parsed_refs
+global mode
 
 from_mark = merge_mark = None
 
@@ -482,7 +529,9 @@ def parse_commit(parser):
 return of['ctx']
 is_exec = of['mode'] == 'x'
 is_link = of['mode'] == 'l'
-return context.memfilectx(f, of['data'], is_link, is_exec, None)
+rename = of.get('rename', None)
+return context.memfilectx(f, of['data'],
+is_link, is_exec, rename)
 
 repo = parser.repo
 
@@ -509,6 +558,21 @@ def parse_commit(parser):
 if merge_mark:
 get_merge_files(repo, p1, p2, files)
 
+if mode == 'hg':
+i = data.find('\n--HG--\n')
+if i >= 0:
+tmp = data[i + len('\n--HG--\n'):].strip()
+for k, v in [e.split(' : ') for e in tmp.split('\n')]:
+if k == 'rename':
+old, new = v.split(' => ', 1)
+files[new]['rename'] = old
+elif k == 'branch':
+extra[k] = v
+elif k == 'extra':
+ek, ev = v.split(' : ', 1)
+extra[ek] = urllib.unquote(ev)
+data = data[:i]
+
 ctx = context.memctx(repo, (p1, p2), data,
 files.keys(), getfilectx,
 user, (date, tz), extra)
@@ -596,12 +660,25 @@ def do_export(parser):
 def main(args):
 global prefix, dirname, branches, bmarks
 global marks, blob_marks, parsed_refs
-global peer
+global peer, mode
 
 alias = args[1]
 url = args[2]
 peer = None
 
+cmd = ['git', 'config', '--get', 'remote-hg.hg-git-compat']
+hg_git_compat = False
+try:
+if subprocess.check_output(cmd) == 'true\n':
+hg_git_compat = True
+except subprocess.CalledProcessError:
+pass
+
+if hg_git_compat:
+mode = 'hg'
+else:
+mode = 'git'
+
 if alias[4:] == url:
 is_tmp = True
 alias = util.sha1(alias).hex

[PATCH v6 05/16] remote-hg: make sure the encoding is correct

2012-11-03 Thread Felipe Contreras
Independently of the environment.

Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index a5023c9..503a9fc 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -9,7 +9,7 @@
 # Then you can clone with:
 # git clone hg::/path/to/mercurial/repo/
 
-from mercurial import hg, ui, bookmarks, context, util
+from mercurial import hg, ui, bookmarks, context, util, encoding
 
 import re
 import sys
@@ -391,6 +391,9 @@ def do_import(parser):
 print "feature export-marks=%s" % path
 sys.stdout.flush()
 
+tmp = encoding.encoding
+encoding.encoding = 'utf-8'
+
 # lets get all the import lines
 while parser.check('import'):
 ref = parser[1]
@@ -409,6 +412,8 @@ def do_import(parser):
 
 parser.next()
 
+encoding.encoding = tmp
+
 print 'done'
 
 def parse_blob(parser):
@@ -491,8 +496,13 @@ def parse_commit(parser):
 files.keys(), getfilectx,
 user, (date, tz), extra)
 
+tmp = encoding.encoding
+encoding.encoding = 'utf-8'
+
 node = repo.commitctx(ctx)
 
+encoding.encoding = tmp
+
 rev = repo[node].rev()
 
 parsed_refs[ref] = node
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 04/16] remote-hg: add support to push URLs

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 45629e0..a5023c9 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -9,12 +9,13 @@
 # Then you can clone with:
 # git clone hg::/path/to/mercurial/repo/
 
-from mercurial import hg, ui, bookmarks, context
+from mercurial import hg, ui, bookmarks, context, util
 
 import re
 import sys
 import os
 import json
+import shutil
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
@@ -574,6 +575,12 @@ def main(args):
 url = args[2]
 peer = None
 
+if alias[4:] == url:
+is_tmp = True
+alias = util.sha1(alias).hexdigest()
+else:
+is_tmp = False
+
 gitdir = os.environ['GIT_DIR']
 dirname = os.path.join(gitdir, 'hg', alias)
 branches = {}
@@ -604,6 +611,9 @@ def main(args):
 die('unhandled command: %s' % line)
 sys.stdout.flush()
 
-marks.store()
+if not is_tmp:
+marks.store()
+else:
+shutil.rmtree(dirname)
 
 sys.exit(main(sys.argv))
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 03/16] remote-hg: add support for remote pushing

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index fcceede..45629e0 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -197,7 +197,7 @@ def fixup_user(user):
 return '%s <%s>' % (name, mail)
 
 def get_repo(url, alias):
-global dirname
+global dirname, peer
 
 myui = ui.ui()
 myui.setconfig('ui', 'interactive', 'off')
@@ -526,7 +526,7 @@ def parse_tag(parser):
 # nothing to do
 
 def do_export(parser):
-global parsed_refs, bmarks
+global parsed_refs, bmarks, peer
 
 parser.next()
 
@@ -562,12 +562,17 @@ def do_export(parser):
 
 print
 
+if peer:
+parser.repo.push(peer, force=False)
+
 def main(args):
 global prefix, dirname, branches, bmarks
 global marks, blob_marks, parsed_refs
+global peer
 
 alias = args[1]
 url = args[2]
+peer = None
 
 gitdir = os.environ['GIT_DIR']
 dirname = os.path.join(gitdir, 'hg', alias)
-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 02/16] remote-hg: add support for pushing

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 217 ++-
 1 file changed, 215 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index e37e278..fcceede 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -9,7 +9,7 @@
 # Then you can clone with:
 # git clone hg::/path/to/mercurial/repo/
 
-from mercurial import hg, ui, bookmarks
+from mercurial import hg, ui, bookmarks, context
 
 import re
 import sys
@@ -18,6 +18,7 @@ import json
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.+)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
 sys.stderr.write('ERROR: %s\n' % (msg % args))
@@ -32,12 +33,17 @@ def gitmode(flags):
 def gittz(tz):
 return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
 
+def hgmode(mode):
+m = { '0100755': 'x', '012': 'l' }
+return m.get(mode, '')
+
 class Marks:
 
 def __init__(self, path):
 self.path = path
 self.tips = {}
 self.marks = {}
+self.rev_marks = {}
 self.last_mark = 0
 
 self.load()
@@ -52,6 +58,9 @@ class Marks:
 self.marks = tmp['marks']
 self.last_mark = tmp['last-mark']
 
+for rev, mark in self.marks.iteritems():
+self.rev_marks[mark] = int(rev)
+
 def dict(self):
 return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : 
self.last_mark }
 
@@ -64,11 +73,19 @@ class Marks:
 def from_rev(self, rev):
 return self.marks[str(rev)]
 
+def to_rev(self, mark):
+return self.rev_marks[mark]
+
 def get_mark(self, rev):
 self.last_mark += 1
 self.marks[str(rev)] = self.last_mark
 return self.last_mark
 
+def new_mark(self, rev, mark):
+self.marks[str(rev)] = mark
+self.rev_marks[mark] = rev
+self.last_mark = mark
+
 def is_marked(self, rev):
 return self.marks.has_key(str(rev))
 
@@ -106,6 +123,35 @@ class Parser:
 if self.line == 'done':
 self.line = None
 
+def get_mark(self):
+i = self.line.index(':') + 1
+return int(self.line[i:])
+
+def get_data(self):
+if not self.check('data'):
+return None
+i = self.line.index(' ') + 1
+size = int(self.line[i:])
+return sys.stdin.read(size)
+
+def get_author(self):
+m = RAW_AUTHOR_RE.match(self.line)
+if not m:
+return None
+_, name, email, date, tz = m.groups()
+
+if email != 'unknown':
+if name:
+user = '%s <%s>' % (name, email)
+else:
+user = '<%s>' % (email)
+else:
+user = name
+
+tz = int(tz)
+tz = ((tz / 100) * 3600) + ((tz % 100) * 60)
+return (user, int(date), -tz)
+
 def export_file(fc):
 d = fc.data()
 print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
@@ -174,6 +220,10 @@ def rev_to_mark(rev):
 global marks
 return marks.from_rev(rev)
 
+def mark_to_rev(mark):
+global marks
+return marks.to_rev(mark)
+
 def export_ref(repo, name, kind, head):
 global prefix, marks
 
@@ -263,9 +313,17 @@ def do_capabilities(parser):
 global prefix, dirname
 
 print "import"
+print "export"
 print "refspec refs/heads/branches/*:%s/branches/*" % prefix
 print "refspec refs/heads/*:%s/bookmarks/*" % prefix
 print "refspec refs/tags/*:%s/tags/*" % prefix
+
+path = os.path.join(dirname, 'marks-git')
+
+if os.path.exists(path):
+print "*import-marks %s" % path
+print "*export-marks %s" % path
+
 print
 
 def get_branch_tip(repo, branch):
@@ -352,8 +410,161 @@ def do_import(parser):
 
 print 'done'
 
+def parse_blob(parser):
+global blob_marks
+
+parser.next()
+mark = parser.get_mark()
+parser.next()
+data = parser.get_data()
+blob_marks[mark] = data
+parser.next()
+return
+
+def parse_commit(parser):
+global marks, blob_marks, bmarks, parsed_refs
+
+from_mark = merge_mark = None
+
+ref = parser[1]
+parser.next()
+
+commit_mark = parser.get_mark()
+parser.next()
+author = parser.get_author()
+parser.next()
+committer = parser.get_author()
+parser.next()
+data = parser.get_data()
+parser.next()
+if parser.check('from'):
+from_mark = parser.get_mark()
+parser.next()
+if parser.check('merge'):
+merge_mark = parser.get_mark()
+parser.next()
+if parser.check('merge'):
+die('octopus merges are not supported yet')
+
+files = {}
+
+for line in parser:
+if parser.check('M'):
+t, m, mark_ref, path = line.split(' ')
+mark = int(mark_ref[1:])
+f = { 'mode' : hgmode(m), 'data' : blob_marks[mark] }

[PATCH v6 00/16] New remote-hg helper:w

2012-11-03 Thread Felipe Contreras
Hi,

Only a few updates, and has been moved to contrib/remote-helpers
(git-remote-bzr is on the way).

This remote-hg has advantages other tools don't have:

 * Uses transport-helper (git clone hg::path)
 * The code is small
 * The code is simple
 * No external dependencies (other than mercurial)
 * It's easy to install (put into your path)
 * Has extensive tests (for real)
 * Active development
 * Has compatibility with hg-git
 * The required patches are available
 * No changes necesary to git core
 * Support for bookmarks
 * Support for tags

One important alternative is the one written by Sverre Rabbelier that is
now maintained and distributed in msysgit. A list of issues with that
approach (not exhaustive):

 * Doesn't work on newer versions of mercurial
 * There are multiple versions, each with different issues
 * Don't pass a single of this remote-hg's tests

To use it add it to your $PATH (e.g. ~/bin).

 % git clone hd:///full/path/or/url/to/hg/repo

To run the tests:

 % make -C contrib/remote-helpers test

The only caveat is that you need 'python' in your $PATH.

Changes since v5:

 * Move to contrib/remote-helpers
 * Reorganize tests
 * Fix update of bookmarks
 * Fix for older versions of python
 * Performance improvements
 * Improve default branch/bookmark handling
 * Add fixes test-lib
 * Cleanups

Changes since v4:

Felipe Contreras (16):
  Add new remote-hg transport helper
  remote-hg: add support for pushing
  remote-hg: add support for remote pushing
  remote-hg: add support to push URLs
  remote-hg: make sure the encoding is correct
  remote-hg: match hg merge behavior
  remote-hg: add support for hg-git compat mode
  remote-hg: add compat for hg-git author fixes
  remote-hg: fake bookmark when there's none
  remote-hg: add basic tests
  test-lib: avoid full path to store test results
  remote-hg: add bidirectional tests
  remote-hg: add tests to compare with hg-git
  remote-hg: add extra author test
  remote-hg: add option to not track branches
  remote-hg: the author email can be null

 contrib/remote-helpers/Makefile  |  13 +
 contrib/remote-helpers/git-remote-hg | 785 +++
 contrib/remote-helpers/test-hg-bidi.sh   | 243 ++
 contrib/remote-helpers/test-hg-hg-git.sh | 466 ++
 contrib/remote-helpers/test-hg.sh| 112 +
 t/test-lib.sh|   3 +-
 6 files changed, 1621 insertions(+), 1 deletion(-)
 create mode 100644 contrib/remote-helpers/Makefile
 create mode 100755 contrib/remote-helpers/git-remote-hg
 create mode 100755 contrib/remote-helpers/test-hg-bidi.sh
 create mode 100755 contrib/remote-helpers/test-hg-hg-git.sh
 create mode 100755 contrib/remote-helpers/test-hg.sh

-- 
1.8.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v6 01/16] Add new remote-hg transport helper

2012-11-03 Thread Felipe Contreras
Signed-off-by: Felipe Contreras 
---
 contrib/remote-helpers/git-remote-hg | 391 +++
 1 file changed, 391 insertions(+)
 create mode 100755 contrib/remote-helpers/git-remote-hg

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
new file mode 100755
index 000..e37e278
--- /dev/null
+++ b/contrib/remote-helpers/git-remote-hg
@@ -0,0 +1,391 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+# Inspired by Rocco Rutte's hg-fast-export
+
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# git clone hg::/path/to/mercurial/repo/
+
+from mercurial import hg, ui, bookmarks
+
+import re
+import sys
+import os
+import json
+
+NAME_RE = re.compile('^([^<>]+)')
+AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]+)>$')
+
+def die(msg, *args):
+sys.stderr.write('ERROR: %s\n' % (msg % args))
+sys.exit(1)
+
+def warn(msg, *args):
+sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gitmode(flags):
+return 'l' in flags and '12' or 'x' in flags and '100755' or '100644'
+
+def gittz(tz):
+return '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
+
+class Marks:
+
+def __init__(self, path):
+self.path = path
+self.tips = {}
+self.marks = {}
+self.last_mark = 0
+
+self.load()
+
+def load(self):
+if not os.path.exists(self.path):
+return
+
+tmp = json.load(open(self.path))
+
+self.tips = tmp['tips']
+self.marks = tmp['marks']
+self.last_mark = tmp['last-mark']
+
+def dict(self):
+return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : 
self.last_mark }
+
+def store(self):
+json.dump(self.dict(), open(self.path, 'w'))
+
+def __str__(self):
+return str(self.dict())
+
+def from_rev(self, rev):
+return self.marks[str(rev)]
+
+def get_mark(self, rev):
+self.last_mark += 1
+self.marks[str(rev)] = self.last_mark
+return self.last_mark
+
+def is_marked(self, rev):
+return self.marks.has_key(str(rev))
+
+def get_tip(self, branch):
+return self.tips.get(branch, 0)
+
+def set_tip(self, branch, tip):
+self.tips[branch] = tip
+
+class Parser:
+
+def __init__(self, repo):
+self.repo = repo
+self.line = self.get_line()
+
+def get_line(self):
+return sys.stdin.readline().strip()
+
+def __getitem__(self, i):
+return self.line.split()[i]
+
+def check(self, word):
+return self.line.startswith(word)
+
+def each_block(self, separator):
+while self.line != separator:
+yield self.line
+self.line = self.get_line()
+
+def __iter__(self):
+return self.each_block('')
+
+def next(self):
+self.line = self.get_line()
+if self.line == 'done':
+self.line = None
+
+def export_file(fc):
+d = fc.data()
+print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
+print "data %d" % len(d)
+print d
+
+def get_filechanges(repo, ctx, parent):
+modified = set()
+added = set()
+removed = set()
+
+cur = ctx.manifest()
+prev = repo[parent].manifest().copy()
+
+for fn in cur:
+if fn in prev:
+if (cur.flags(fn) != prev.flags(fn) or cur[fn] != prev[fn]):
+modified.add(fn)
+del prev[fn]
+else:
+added.add(fn)
+removed |= set(prev.keys())
+
+return added | modified, removed
+
+def fixup_user(user):
+user = user.replace('"', '')
+name = mail = None
+m = AUTHOR_RE.match(user)
+if m:
+name = m.group(1)
+mail = m.group(2).strip()
+else:
+m = NAME_RE.match(user)
+if m:
+name = m.group(1).strip()
+
+if not name:
+name = 'Unknown'
+if not mail:
+mail = 'unknown'
+
+return '%s <%s>' % (name, mail)
+
+def get_repo(url, alias):
+global dirname
+
+myui = ui.ui()
+myui.setconfig('ui', 'interactive', 'off')
+
+if hg.islocal(url):
+repo = hg.repository(myui, url)
+else:
+local_path = os.path.join(dirname, 'clone')
+if not os.path.exists(local_path):
+peer, dstpeer = hg.clone(myui, {}, url, local_path, update=False, 
pull=True)
+repo = dstpeer.local()
+else:
+repo = hg.repository(myui, local_path)
+peer = hg.peer(myui, {}, url)
+repo.pull(peer, heads=None, force=True)
+
+return repo
+
+def rev_to_mark(rev):
+global marks
+return marks.from_rev(rev)
+
+def export_ref(repo, name, kind, head):
+global prefix, marks
+
+ename = '%s/%s' % (kind, name)
+tip = marks.get_tip(ename)
+
+# mercurial takes too much time checking this
+if tip and tip == head.rev():
+# nothing to do
+return
+revs = repo.revs('%u:%u' % (tip, head))
+count = 0
+
+  

Re: git-p4 clone @all error

2012-11-03 Thread Pete Wyckoff
merlin...@gmail.com wrote on Wed, 31 Oct 2012 15:01 +0100:
> On Tue, Oct 30, 2012 at 11:44 AM, Arthur  wrote:
> > The problem :
> >
> > Importing revision 7727 (100%)Traceback (most recent call last):
> >   File "/usr/bin/git-p4", line 3183, in 
> > main()
> >   File "/usr/bin/git-p4", line 3177, in main
> > if not cmd.run(args):
> >   File "/usr/bin/git-p4", line 3048, in run
> > if not P4Sync.run(self, depotPaths):
> >   File "/usr/bin/git-p4", line 2911, in run
> > self.importChanges(changes)
> >   File "/usr/bin/git-p4", line 2618, in importChanges
> > self.initialParent)
> >   File "/usr/bin/git-p4", line 2198, in commit
> > epoch = details["time"]
> > KeyError: 'time'
> 
> Are you permanently converting a project, or are you planning to
> continue submitting to perforce with git-p4?
> 
> I have seen similar bugs myself when using the --detect-branches
> option.

I hope --detect-branches is unrelated to any problems related to
p4 describe, because it is used identically both with and without
the option.  But you never know.

> The branch detection in git-p4 is flaky anyway: it is limited
> what it can handle, and it used to require correct perforce branch
> specs at least, so I would recommend not using it unless you know what
> it is doing under the hood.

It relies on heuristics because the git idea of branches doesn't
have a direct analog in p4, even though p4 users will organize
their files and directories in ways that suggest branches.  The
way it works is described in the BRANCH DETECTION part of the
git-p4.1 man page.

The man page also explains how you can use a config variable
to explicitly define the branch relationships.  This might help:

git-p4.branchList::
List of branches to be imported when branch detection is
enabled.  Each entry should be a pair of branch names separated
by a colon (:).  This example declares that both branchA and
branchB were created from main:

git config   git-p4.branchList main:branchA
git config --add git-p4.branchList main:branchB

It still only works for branches at the same "level" of the
depot path.

> Instead I would just clone a single branch at a time (drop the
> --detect-branches) and work on that.
> 
> I do this even in the rare cases when I need more than one perforce
> branch in the same git repo - there are other ways to achieve the same
> thing.

Yep, that should alway works.

-- Pete
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] git p4: catch p4 describe errors

2012-11-03 Thread Matt Arsenault

On Nov 3, 2012, at 16:07 , Pete Wyckoff  wrote:
> 
> Arthur and Matt, you've both had intermittent "p4 describe"
> errors.  I've not been able to repeat this or come up with
> a possible root cause.  But it is clear that the error handling
> in this area is weak.
I tried this week to find the commit that caused the problem, but there were 
too many to sift through so I haven't managed to see it again either--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] git p4: catch p4 describe errors

2012-11-03 Thread Pete Wyckoff
Group the two calls to "p4 describe" into a new helper function,
and try to validate the p4 results.  The current behavior when p4
describe fails is to die with a python backtrace.  The new behavior
will print the full response.

Based-on-patch-by: Matt Arsenault 
Signed-off-by: Pete Wyckoff 
---

Arthur and Matt, you've both had intermittent "p4 describe"
errors.  I've not been able to repeat this or come up with
a possible root cause.  But it is clear that the error handling
in this area is weak.

Can you continue using git-p4 with this patch applied?  If
it fails again, at least we'll get some interesting output.

This is appropriate for upstream too, since it should do no harm
and might flush out a bug at some point.  It includes "-s" on
both p4 describe calls now as Matt suggested.

-- Pete

 git-p4.py | 35 ++-
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/git-p4.py b/git-p4.py
index 882b1bb..e51a081 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -169,6 +169,29 @@ def p4_reopen(type, f):
 def p4_move(src, dest):
 p4_system(["move", "-k", wildcard_encode(src), wildcard_encode(dest)])
 
+def p4_describe(change):
+"""Make sure it returns a valid result by checking for
+   the presence of field "time".  Return a dict of the
+   results."""
+
+ds = p4CmdList(["describe", "-s", str(change)])
+if len(ds) != 1:
+die("p4 describe -s %d did not return 1 result: %s" % (change, 
str(ds)))
+
+d = ds[0]
+
+if "p4ExitCode" in d:
+die("p4 describe -s %d exited with %d: %s" % (change, d["p4ExitCode"],
+  str(d)))
+if "code" in d:
+if d["code"] == "error":
+die("p4 describe -s %d returned error code: %s" % (change, str(d)))
+
+if "time" not in d:
+die("p4 describe -s %d returned no \"time\": %s" % (change, str(d)))
+
+return d
+
 #
 # Canonicalize the p4 type and return a tuple of the
 # base type, plus any modifiers.  See "p4 help filetypes"
@@ -2543,7 +2566,7 @@ class P4Sync(Command, P4UserMap):
 def importChanges(self, changes):
 cnt = 1
 for change in changes:
-description = p4Cmd(["describe", str(change)])
+description = p4_describe(change)
 self.updateOptionDict(description)
 
 if not self.silent:
@@ -2667,14 +2690,8 @@ class P4Sync(Command, P4UserMap):
 
 # Use time from top-most change so that all git p4 clones of
 # the same p4 repo have the same commit SHA1s.
-res = p4CmdList("describe -s %d" % newestRevision)
-newestTime = None
-for r in res:
-if r.has_key('time'):
-newestTime = int(r['time'])
-if newestTime is None:
-die("\"describe -s\" on newest change %d did not give a time")
-details["time"] = newestTime
+res = p4_describe(newestRevision)
+details["time"] = res["time"]
 
 self.updateOptionDict(details)
 try:
-- 
1.7.12.1.457.g468b3ef

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Enable parallelism in git submodule update.

2012-11-03 Thread Jens Lehmann
Am 03.11.2012 19:44, schrieb Phil Hord:
> On Sat, Nov 3, 2012 at 11:42 AM, Jens Lehmann  wrote:
>> Am 30.10.2012 19:11, schrieb Stefan Zager:
>>> This is a refresh of a conversation from a couple of months ago.
>>>
>>> I didn't try to implement all the desired features (e.g., smart logic
>>> for passing a -j parameter to recursive submodule invocations), but I
>>> did address the one issue that Junio insisted on: the code makes a
>>> best effort to detect whether xargs supports parallel execution on the
>>> host platform, and if it doesn't, then it prints a warning and falls
>>> back to serial execution.
>>
>> I suspect not passing on --jobs recursively like you do here is the
>> right thing to do, as that would give exponential growth of jobs with
>> recursion depth, which makes no sense to me.
> 
> On the other hand, since $jobs is still defined when the recursive
> call to is made to 'eval cmd_update "$orig_flags"', I suspect the
> value *is* passed down recursively.

But for $jobs != 1 Stefan's code doesn't use eval cmd_update but
starts the submodule script again:

+   xargs $max_lines -P "$jobs" git submodule update 
$orig_flags

That should get rid of the $jobs setting, or am I missing something?

>  Maybe $jobs should be manually
> reset before recursing -- unless it is "0" -- though I expect someone
> would feel differently if she had one submodule on level 1 and 10
> submodules on level 2.  She would be surprised, then, when  --jobs=10
> seemed to have little affect on performance.

Hmm, good point. However we implement that, it should at least be
properly documented in the man page (and in the use case you describe
a "git submodule foreach 'git submodule update -j 10'" could be the
solution if we choose to not propagate the jobs option).

>  So maybe it is best to
> leave it as it is, excepting that the apparent attempt not to pass the
> switch down is probably misleading.

I didn't test it, but I think it should work (famous last words ;-).
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Enable parallelism in git submodule update.

2012-11-03 Thread Jens Lehmann
Am 29.07.2012 17:37, schrieb Jens Lehmann:
> Am 27.07.2012 20:37, schrieb Stefan Zager:
>> The --jobs parameter may be used to set the degree of per-submodule
>> parallel execution.
> 
> I think this is a sound idea, but it would be good to see some
> actual measurements. What are the performance numbers with and
> without this change? Which cases do benefit and are there some
> which run slower when run in parallel?

ping?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Wrap commit messages on `git commit -m`

2012-11-03 Thread Phil Hord
On Sat, Nov 3, 2012 at 3:41 AM, David Aguilar  wrote:
> On Fri, Nov 2, 2012 at 11:38 PM, Jonathan Nieder  wrote:
>> Ramkumar Ramachandra wrote:
>>> Jonathan Nieder wrote:
>>
 Ram, what platform do your colleagues use?
>>>
>>> Red Hat Enterprise Linux 5.
>>
>> Oh, ok.  In that case I blame habit.
>>
>> I think the best option you have is to just complain to your
>> colleagues about the long lines.  Then they would get a chance to
>> explore what the UI currently offers and to complain to this list
>> (perhaps via you :)) about missing features that would make their work
>> easier.
>>
>> To put it another way: I don't see yet how a hypothetical "git commit
>> --wrap-lines -m 'long message'" would make life easier than just
>> running "git commit" and entering the message using $EDITOR.  There's
>> probably a UI or documentation bug lurking somewhere, so thanks for
>> thinking about these things.
>>
>> Regards,
>> Jonathan
>
> If your colleagues do not mind using a GUI then git-cola
> might help them form better commit messages.
>
> It auto-wraps long lines and enforces a very clear distinction
> between the one-line summary and extended description.

vim also does this nicely with syntax highlighting turned on, though I
do not know how this feature is triggered.

Specifically, it wraps all lines at 72 characters; it colors line 1
yellow out to 50 characters and white after that; and it colors any
text on line 2 with a red background (should be empty).

Phil
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Enable parallelism in git submodule update.

2012-11-03 Thread Phil Hord
On Sat, Nov 3, 2012 at 11:42 AM, Jens Lehmann  wrote:
> Am 30.10.2012 19:11, schrieb Stefan Zager:
>> This is a refresh of a conversation from a couple of months ago.
>>
>> I didn't try to implement all the desired features (e.g., smart logic
>> for passing a -j parameter to recursive submodule invocations), but I
>> did address the one issue that Junio insisted on: the code makes a
>> best effort to detect whether xargs supports parallel execution on the
>> host platform, and if it doesn't, then it prints a warning and falls
>> back to serial execution.
>
> I suspect not passing on --jobs recursively like you do here is the
> right thing to do, as that would give exponential growth of jobs with
> recursion depth, which makes no sense to me.

On the other hand, since $jobs is still defined when the recursive
call to is made to 'eval cmd_update "$orig_flags"', I suspect the
value *is* passed down recursively.  Maybe $jobs should be manually
reset before recursing -- unless it is "0" -- though I expect someone
would feel differently if she had one submodule on level 1 and 10
submodules on level 2.  She would be surprised, then, when  --jobs=10
seemed to have little affect on performance.  So maybe it is best to
leave it as it is, excepting that the apparent attempt not to pass the
switch down is probably misleading.

Phil
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Enable parallelism in git submodule update.

2012-11-03 Thread Jens Lehmann
Am 30.10.2012 19:11, schrieb Stefan Zager:
> This is a refresh of a conversation from a couple of months ago.
> 
> I didn't try to implement all the desired features (e.g., smart logic
> for passing a -j parameter to recursive submodule invocations), but I
> did address the one issue that Junio insisted on: the code makes a
> best effort to detect whether xargs supports parallel execution on the
> host platform, and if it doesn't, then it prints a warning and falls
> back to serial execution.

I suspect not passing on --jobs recursively like you do here is the
right thing to do, as that would give exponential growth of jobs with
recursion depth, which makes no sense to me.

A still unsolved issue is the unstructured output from the different
update jobs. It'll be hard (if not impossible) to see in what submodule
which update took place (or failed). I think we should have a solution
for that too (maybe one of those Heiko mentioned or something as simple
as implying "-q"?).

> Stefan
> 
> On Tue, Oct 30, 2012 at 11:03 AM,   wrote:
>> The --jobs parameter may be used to set the degree of per-submodule
>> parallel execution.
>
>> Signed-off-by: Stefan Zager 
>> ---
>>  Documentation/git-submodule.txt |8 ++-
>>  git-submodule.sh|   40 
>> ++-
>>  2 files changed, 46 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/git-submodule.txt 
>> b/Documentation/git-submodule.txt
>> index b4683bb..cb23ba7 100644
>> --- a/Documentation/git-submodule.txt
>> +++ b/Documentation/git-submodule.txt
>> @@ -14,7 +14,8 @@ SYNOPSIS
>>  'git submodule' [--quiet] status [--cached] [--recursive] [--] [...]
>>  'git submodule' [--quiet] init [--] [...]
>>  'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
>> - [--reference ] [--merge] [--recursive] [--] 
>> [...]
>> + [--reference ] [--merge] [--recursive]
>> + [-j|--jobs [jobs]] [--] [...]
>>  'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) 
>> ]
>>   [commit] [--] [...]
>>  'git submodule' [--quiet] foreach [--recursive] 
>> @@ -146,6 +147,11 @@ If the submodule is not yet initialized, and you just 
>> want to use the
>>  setting as stored in .gitmodules, you can automatically initialize the
>>  submodule with the `--init` option.
>>  +
>> +By default, each submodule is treated serially.  You may specify a degree of
>> +parallel execution with the --jobs flag.  If a parameter is provided, it is
>> +the maximum number of jobs to run in parallel; without a parameter, all 
>> jobs are
>> +run in parallel.
>> ++

The new "--jobs" option should be documented under "OPTIONS", (and maybe
include that "--jobs 0" does the same as "--jobs" alone and that this is
not supported on all platforms).

>>  If `--recursive` is specified, this command will recurse into the
>>  registered submodules, and update any nested submodules within.
>>  +
>> diff --git a/git-submodule.sh b/git-submodule.sh
>> index ab6b110..60a5f96 100755
>> --- a/git-submodule.sh
>> +++ b/git-submodule.sh
>> @@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
>>  USAGE="[--quiet] add [-b branch] [-f|--force] [--reference ] 
>> [--]  []
>> or: $dashless [--quiet] status [--cached] [--recursive] [--] [...]
>> or: $dashless [--quiet] init [--] [...]
>> -   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] 
>> [--rebase] [--reference ] [--merge] [--recursive] [--] 
>> [...]
>> +   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] 
>> [--rebase] [--reference ] [--merge] [--recursive] [-j|--jobs 
>> [jobs]] [--] [...]
>> or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] 
>> [commit] [--] [...]
>> or: $dashless [--quiet] foreach [--recursive] 
>> or: $dashless [--quiet] sync [--] [...]"
>> @@ -500,6 +500,7 @@ cmd_update()
>>  {
>> # parse $args after "submodule ... update".
>> orig_flags=
>> +   jobs="1"
>> while test $# -ne 0
>> do
>> case "$1" in
>> @@ -518,6 +519,20 @@ cmd_update()
>> -r|--rebase)
>> update="rebase"
>> ;;
>> +   -j|--jobs)
>> +   case "$2" in
>> +   ''|-*)
>> +   jobs="0"
>> +   ;;
>> +   *)
>> +   jobs="$2"
>> +   shift
>> +   ;;
>> +   esac
>> +   # Don't preserve this arg.
>> +   shift
>> +   continue
>> +   ;;
>> --reference)
>> case "$2" in '') usage ;; esac
>> reference="--reference=$2"
>> @@ -551,11 +566,34 @@ cmd_update()
>> shift
>> done
>>
>> +  

Re: git-p4 clone @all error

2012-11-03 Thread Pete Wyckoff
a.fou...@amesys.fr wrote on Tue, 30 Oct 2012 03:44 -0700:
> So, i want import my perforce projet on my server git.
> 
> perforce my project tree :
> 
> depot
>   dev_data
>   mainline
>   release_1.0
>   release_1.0.0
> 
> my command is :
> 
> git-p4 clone -v --detect-branches //depot@all /home/user/projets/deport
> 
> The problem :
> 
> Importing revision 7727 (100%)Traceback (most recent call last):
>   File "/usr/bin/git-p4", line 3183, in 
> main()
>   File "/usr/bin/git-p4", line 3177, in main
> if not cmd.run(args):
>   File "/usr/bin/git-p4", line 3048, in run
> if not P4Sync.run(self, depotPaths):
>   File "/usr/bin/git-p4", line 2911, in run
> self.importChanges(changes)
>   File "/usr/bin/git-p4", line 2618, in importChanges
> self.initialParent)
>   File "/usr/bin/git-p4", line 2198, in commit
> epoch = details["time"]
> KeyError: 'time'

This isn't the --detect-branches code path, as far as I can tell.
Line 2618, importChanges, is the not-detect case.  But either
way, I suspect that p4 returns results we weren't expecting, and
this is just the symptom of that problem.

> if i make a p4 sync //depot/...#head on my perforce server i've this error : 
> Librarian checkout
> depot/mainline/xxx/api429decryption.txt failed.
> open for read: depot/mainline/xx/api429decryption.txt,v: Le
> fichier spcifi est introuvable.
> 
> My p4 clone can't checking out files after importing revision..

I've seen this before at our site.  If you search for "librarian
checout" you'll see lots of messages suggesting there's some sort
of problem with the p4 server.

I'm going to work on a patch to git-p4 to make it print a more
useful diagnostic in the case of your error above.  Can you
make this problem occur reliably?

-- Pete
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Wrap commit messages on `git commit -m`

2012-11-03 Thread David Aguilar
On Fri, Nov 2, 2012 at 11:38 PM, Jonathan Nieder  wrote:
> Ramkumar Ramachandra wrote:
>> Jonathan Nieder wrote:
>
>>> Ram, what platform do your colleagues use?
>>
>> Red Hat Enterprise Linux 5.
>
> Oh, ok.  In that case I blame habit.
>
> I think the best option you have is to just complain to your
> colleagues about the long lines.  Then they would get a chance to
> explore what the UI currently offers and to complain to this list
> (perhaps via you :)) about missing features that would make their work
> easier.
>
> To put it another way: I don't see yet how a hypothetical "git commit
> --wrap-lines -m 'long message'" would make life easier than just
> running "git commit" and entering the message using $EDITOR.  There's
> probably a UI or documentation bug lurking somewhere, so thanks for
> thinking about these things.
>
> Regards,
> Jonathan

If your colleagues do not mind using a GUI then git-cola
might help them form better commit messages.

It auto-wraps long lines and enforces a very clear distinction
between the one-line summary and extended description.
-- 
David
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html