* [PATCH 3/3] remote-bzr: add simple tests
From: Felipe Contreras @ 2012-11-04 2:22 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jeff King, Johannes Schindelin, Felipe Contreras
In-Reply-To: <1351995723-20396-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
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 0000000..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=<<EOF
+import bzrlib
+bzrlib.initialize()
+import bzrlib.plugin
+bzrlib.plugin.load_plugins()
+import bzrlib.plugins.fastimport
+EOF
+
+if ! "$PYTHON_PATH" -c "$cmd"; then
+ echo "consider setting BZR_PLUGIN_PATH=$HOME/.bazaar/plugins" 1>&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 <author@example.com>"
+
+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
^ permalink raw reply related
* [PATCH 2/3] remote-bzr: add support for pushing
From: Felipe Contreras @ 2012-11-04 2:22 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Jeff King, Johannes Schindelin, Felipe Contreras
In-Reply-To: <1351995723-20396-1-git-send-email-felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
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
^ permalink raw reply related
* Re: [PATCH v4 00/13] New remote-hg helper
From: Felipe Contreras @ 2012-11-04 2:28 UTC (permalink / raw)
To: Jeff King
Cc: Michael J Gruber, Johannes Schindelin, git, Junio C Hamano,
Sverre Rabbelier, Ilari Liusvaara, Daniel Barkalow
In-Reply-To: <CAMP44s0DyiH+ac-xnfmJ3+JSib+y8GYZZymM83HUjKi5CuqARg@mail.gmail.com>
On Fri, Nov 2, 2012 at 8:20 PM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> On Fri, Nov 2, 2012 at 7:39 PM, Felipe Contreras
> <felipe.contreras@gmail.com> 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
^ permalink raw reply
* [PATCH 0/4] Simplify and document strbuf_split() functions
From: Michael Haggerty @ 2012-11-04 6:46 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, 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
^ permalink raw reply
* [PATCH 1/4] strbuf_split_buf(): use ALLOC_GROW()
From: Michael Haggerty @ 2012-11-04 6:46 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352011614-29334-1-git-send-email-mhagger@alum.mit.edu>
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 <mhagger@alum.mit.edu>
---
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
^ permalink raw reply related
* [PATCH 2/4] strbuf_split_buf(): simplify iteration
From: Michael Haggerty @ 2012-11-04 6:46 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352011614-29334-1-git-send-email-mhagger@alum.mit.edu>
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 <mhagger@alum.mit.edu>
---
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
^ permalink raw reply related
* [PATCH 3/4] strbuf_split*(): rename "delim" parameter to "terminator"
From: Michael Haggerty @ 2012-11-04 6:46 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352011614-29334-1-git-send-email-mhagger@alum.mit.edu>
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 <mhagger@alum.mit.edu>
---
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
^ permalink raw reply related
* [PATCH 4/4] strbuf_split*(): document functions
From: Michael Haggerty @ 2012-11-04 6:46 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352011614-29334-1-git-send-email-mhagger@alum.mit.edu>
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 <mhagger@alum.mit.edu>
---
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
^ permalink raw reply related
* [PATCH 0/5] Use string_lists when processing notes
From: Michael Haggerty @ 2012-11-04 7:07 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
This simplifies the code. Also, sort lines all at once (O(N lg N))
rather than insertion sorting as lines are processed (O(N^2)) and fix
the handling of empty values in GIT_NOTES_DISPLAY_REF and
GIT_NOTES_REWRITE_REF.
Michael Haggerty (5):
string_list: add a function string_list_remove_empty_items()
Initialize sort_uniq_list using named constant
combine_notes_cat_sort_uniq(): sort and dedup lines all at once
notes: fix handling of colon-separated values
string_list_add_refs_from_colon_sep(): use string_list_split()
Documentation/technical/api-string-list.txt | 9 ++++-
notes.c | 61 ++++++++++++-----------------
string-list.c | 9 +++++
string-list.h | 7 ++++
4 files changed, 49 insertions(+), 37 deletions(-)
--
1.8.0
^ permalink raw reply
* [PATCH 1/5] string_list: add a function string_list_remove_empty_items()
From: Michael Haggerty @ 2012-11-04 7:07 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352012830-13591-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/technical/api-string-list.txt | 9 ++++++++-
string-list.c | 9 +++++++++
string-list.h | 7 +++++++
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 94d7a2b..7386bca 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -38,7 +38,8 @@ member (you need this if you add things later) and you should set the
`unsorted_string_list_delete_item`.
. Can remove items not matching a criterion from a sorted or unsorted
- list using `filter_string_list`.
+ list using `filter_string_list`, or remove empty strings using
+ `string_list_remove_empty_items`.
. Finally it should free the list using `string_list_clear`.
@@ -75,6 +76,12 @@ Functions
to be deleted. Preserve the order of the items that are
retained.
+`string_list_remove_empty_items`::
+
+ Remove any empty strings from the list. If free_util is true,
+ call free() on the util members of any items that have to be
+ deleted. Preserve the order of the items that are retained.
+
`string_list_longest_prefix`::
Return the longest string within a string_list that is a
diff --git a/string-list.c b/string-list.c
index c54b816..397e6cf 100644
--- a/string-list.c
+++ b/string-list.c
@@ -136,6 +136,15 @@ void filter_string_list(struct string_list *list, int free_util,
list->nr = dst;
}
+static int item_is_not_empty(struct string_list_item *item, void *unused)
+{
+ return *item->string != '\0';
+}
+
+void string_list_remove_empty_items(struct string_list *list, int free_util) {
+ filter_string_list(list, free_util, item_is_not_empty, NULL);
+}
+
char *string_list_longest_prefix(const struct string_list *prefixes,
const char *string)
{
diff --git a/string-list.h b/string-list.h
index 5efd07b..c50b0d0 100644
--- a/string-list.h
+++ b/string-list.h
@@ -39,6 +39,13 @@ void filter_string_list(struct string_list *list, int free_util,
string_list_each_func_t want, void *cb_data);
/*
+ * Remove any empty strings from the list. If free_util is true, call
+ * free() on the util members of any items that have to be deleted.
+ * Preserve the order of the items that are retained.
+ */
+void string_list_remove_empty_items(struct string_list *list, int free_util);
+
+/*
* Return the longest string in prefixes that is a prefix (in the
* sense of prefixcmp()) of string, or NULL if no such prefix exists.
* This function does not require the string_list to be sorted (it
--
1.8.0
^ permalink raw reply related
* [PATCH 2/5] Initialize sort_uniq_list using named constant
From: Michael Haggerty @ 2012-11-04 7:07 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352012830-13591-1-git-send-email-mhagger@alum.mit.edu>
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
notes.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/notes.c b/notes.c
index bc454e1..8652f8f 100644
--- a/notes.c
+++ b/notes.c
@@ -901,7 +901,7 @@ static int string_list_join_lines_helper(struct string_list_item *item,
int combine_notes_cat_sort_uniq(unsigned char *cur_sha1,
const unsigned char *new_sha1)
{
- struct string_list sort_uniq_list = { NULL, 0, 0, 1 };
+ struct string_list sort_uniq_list = STRING_LIST_INIT_DUP;
struct strbuf buf = STRBUF_INIT;
int ret = 1;
--
1.8.0
^ permalink raw reply related
* [PATCH 3/5] combine_notes_cat_sort_uniq(): sort and dedup lines all at once
From: Michael Haggerty @ 2012-11-04 7:07 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352012830-13591-1-git-send-email-mhagger@alum.mit.edu>
Instead of reading lines one by one and insertion-sorting them into a
string_list, read all of the lines, sort them, then remove duplicates.
Aside from being less code, this reduces the complexity from O(N^2) to
O(N lg N) in the total number of lines.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
notes.c | 38 ++++++++++++++++----------------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/notes.c b/notes.c
index 8652f8f..62f8f6f 100644
--- a/notes.c
+++ b/notes.c
@@ -848,15 +848,16 @@ int combine_notes_ignore(unsigned char *cur_sha1,
return 0;
}
-static int string_list_add_note_lines(struct string_list *sort_uniq_list,
+/*
+ * Add the lines from the named object to list, with trailing
+ * newlines removed.
+ */
+static int string_list_add_note_lines(struct string_list *list,
const unsigned char *sha1)
{
char *data;
unsigned long len;
enum object_type t;
- struct strbuf buf = STRBUF_INIT;
- struct strbuf **lines = NULL;
- int i, list_index;
if (is_null_sha1(sha1))
return 0;
@@ -868,24 +869,14 @@ static int string_list_add_note_lines(struct string_list *sort_uniq_list,
return t != OBJ_BLOB || !data;
}
- strbuf_attach(&buf, data, len, len + 1);
- lines = strbuf_split(&buf, '\n');
-
- for (i = 0; lines[i]; i++) {
- if (lines[i]->buf[lines[i]->len - 1] == '\n')
- strbuf_setlen(lines[i], lines[i]->len - 1);
- if (!lines[i]->len)
- continue; /* skip empty lines */
- list_index = string_list_find_insert_index(sort_uniq_list,
- lines[i]->buf, 0);
- if (list_index < 0)
- continue; /* skip duplicate lines */
- string_list_insert_at_index(sort_uniq_list, list_index,
- lines[i]->buf);
- }
-
- strbuf_list_free(lines);
- strbuf_release(&buf);
+ /*
+ * If the last line of the file is EOL-terminated, this will
+ * add an empty string to the list. But it will be removed
+ * later, along with any empty strings that came from empty
+ * lines within the file.
+ */
+ string_list_split(list, data, '\n', -1);
+ free(data);
return 0;
}
@@ -910,6 +901,9 @@ int combine_notes_cat_sort_uniq(unsigned char *cur_sha1,
goto out;
if (string_list_add_note_lines(&sort_uniq_list, new_sha1))
goto out;
+ string_list_remove_empty_items(&sort_uniq_list, 0);
+ sort_string_list(&sort_uniq_list);
+ string_list_remove_duplicates(&sort_uniq_list, 0);
/* create a new blob object from sort_uniq_list */
if (for_each_string_list(&sort_uniq_list,
--
1.8.0
^ permalink raw reply related
* [PATCH 4/5] notes: fix handling of colon-separated values
From: Michael Haggerty @ 2012-11-04 7:07 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352012830-13591-1-git-send-email-mhagger@alum.mit.edu>
The substrings output by strbuf_split() include the ':' delimiters.
When processing GIT_NOTES_DISPLAY_REF and GIT_NOTES_REWRITE_REF, strip
off the delimiter character *before* checking whether the substring is
empty rather than after, so that empty strings within the list are
also skipped.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
notes.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/notes.c b/notes.c
index 62f8f6f..63b2a09 100644
--- a/notes.c
+++ b/notes.c
@@ -951,10 +951,10 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,
split = strbuf_split(&globbuf, ':');
for (i = 0; split[i]; i++) {
+ if (split[i]->len && split[i]->buf[split[i]->len-1] == ':')
+ strbuf_setlen(split[i], split[i]->len-1);
if (!split[i]->len)
continue;
- if (split[i]->buf[split[i]->len-1] == ':')
- strbuf_setlen(split[i], split[i]->len-1);
string_list_add_refs_by_glob(list, split[i]->buf);
}
--
1.8.0
^ permalink raw reply related
* [PATCH 5/5] string_list_add_refs_from_colon_sep(): use string_list_split()
From: Michael Haggerty @ 2012-11-04 7:07 UTC (permalink / raw)
To: Jeff King; +Cc: Junio C Hamano, git, Michael Haggerty
In-Reply-To: <1352012830-13591-1-git-send-email-mhagger@alum.mit.edu>
It makes for simpler code than strbuf_split().
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
notes.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/notes.c b/notes.c
index 63b2a09..b823701 100644
--- a/notes.c
+++ b/notes.c
@@ -943,23 +943,18 @@ void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
void string_list_add_refs_from_colon_sep(struct string_list *list,
const char *globs)
{
- struct strbuf globbuf = STRBUF_INIT;
- struct strbuf **split;
+ struct string_list split = STRING_LIST_INIT_NODUP;
+ char *globs_copy = xstrdup(globs);
int i;
- strbuf_addstr(&globbuf, globs);
- split = strbuf_split(&globbuf, ':');
+ string_list_split_in_place(&split, globs_copy, ':', -1);
+ string_list_remove_empty_items(&split, 0);
- for (i = 0; split[i]; i++) {
- if (split[i]->len && split[i]->buf[split[i]->len-1] == ':')
- strbuf_setlen(split[i], split[i]->len-1);
- if (!split[i]->len)
- continue;
- string_list_add_refs_by_glob(list, split[i]->buf);
- }
+ for (i = 0; i < split.nr; i++)
+ string_list_add_refs_by_glob(list, split.items[i].string);
- strbuf_list_free(split);
- strbuf_release(&globbuf);
+ string_list_clear(&split, 0);
+ free(globs_copy);
}
static int notes_display_config(const char *k, const char *v, void *cb)
--
1.8.0
^ permalink raw reply related
* Re: Wrap commit messages on `git commit -m`
From: Tay Ray Chuan @ 2012-11-04 7:27 UTC (permalink / raw)
To: Lars Gullik Bjønnes; +Cc: Ramkumar Ramachandra, git
In-Reply-To: <m3a9v170ca.fsf@black.gullik.net>
On Thu, Nov 1, 2012 at 11:29 AM, Lars Gullik Bjønnes <larsbj@gullik.org> wrote:
> Ramkumar Ramachandra <artagnon@gmail.com> writes:
>
> | Hi,
>>
> | Some of my colleagues are lazy to fire up an editor and write proper
> | commit messages- they often write one-liners using `git commit -m`.
> | However, that line turns out to be longer than 72 characters, and the
> | resulting `git log` output is ugly. So, I was wondering if it would
> | be a good idea to wrap these one-liners to 72 characters
> | automatically.
>
> git commit -m 'foo: fix this problem
>
> This problem is fixed by doing foo,
> bar and baz.
>
> Signed-off-by: me
> '
>
> works.
Perhaps a deeper issue is that the implicit email format
(subject-body) for commit messages, is, well, implicit. New users of
git who type git-commit -m '...' isn't going to know that those few
characters will all be lumped on a "subject" line, forever screwing
themselves when they review the output of git-log, git-rebase
--interactive, etc. (can't remember off the top of my head if
git-format-patch would chop off long subjects and move it to the
body), which may be a significant period of time (and thus commits)
later.
While I don't have any ideas on how to improve on this, hopefully this
gets recognized as an issue in the first place.
--
Cheers,
Ray Chuan
^ permalink raw reply
* Re: [PATCH 1/4] strbuf_split_buf(): use ALLOC_GROW()
From: Jeff King @ 2012-11-04 11:41 UTC (permalink / raw)
To: Michael Haggerty; +Cc: Junio C Hamano, git
In-Reply-To: <1352011614-29334-2-git-send-email-mhagger@alum.mit.edu>
On Sun, Nov 04, 2012 at 07:46:51AM +0100, Michael Haggerty wrote:
> 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.
I suspect this was not used originally because ALLOC_GROW relies on
alloc_nr, which does fast growth early on. At (x+16)*3/2, we end up with
24 slots for the first allocation. We are typically splitting 1 or 2
values.
It probably doesn't make a big difference in practice, though, as we're
talking about wasting less than 200 bytes on a 64-bit platform, and we
do not tend to keep large numbers of split lists around.
-Peff
^ permalink raw reply
* Re: [PATCH 0/4] Simplify and document strbuf_split() functions
From: Jeff King @ 2012-11-04 11:50 UTC (permalink / raw)
To: Michael Haggerty; +Cc: Junio C Hamano, git
In-Reply-To: <1352011614-29334-1-git-send-email-mhagger@alum.mit.edu>
On Sun, Nov 04, 2012 at 07:46:50AM +0100, Michael Haggerty wrote:
> The strbuf_split() family of functions was completely undocumented.
> Add documentation and also simplify the definition of
> strbuf_split_buf().
Thanks. Looks good overall, even with the comments I raised for patch 1
(I think it is not a big deal, and even if it does become a big deal,
the right fix is probably to make alloc_nr smarter about early growth).
-Peff
^ permalink raw reply
* Re: [PATCH 5/5] string_list_add_refs_from_colon_sep(): use string_list_split()
From: Jeff King @ 2012-11-04 11:57 UTC (permalink / raw)
To: Michael Haggerty; +Cc: Junio C Hamano, git
In-Reply-To: <1352012830-13591-6-git-send-email-mhagger@alum.mit.edu>
On Sun, Nov 04, 2012 at 08:07:10AM +0100, Michael Haggerty wrote:
> It makes for simpler code than strbuf_split().
Agreed.
I wonder how useful the strbuf_split functions really are. Callers might
care about splitting content in a strbuf, but in general, getting a list
of strbufs out is just a hassle, and a string_list makes more sense.
It's probably not worth spending time converting them unless we happen
to be working in the area, though.
-Peff
^ permalink raw reply
* Re: What's cooking in git.git (Oct 2012, #09; Mon, 29)
From: Jeff King @ 2012-11-04 12:29 UTC (permalink / raw)
To: Ramsay Jones; +Cc: Chris Rorvick, git
In-Reply-To: <50943C1A.4090706@ramsay1.demon.co.uk>
On Fri, Nov 02, 2012 at 09:33:14PM +0000, Ramsay Jones wrote:
> >> I wonder if Ramsay has an older perl that does not do this special
> >> hackery right. I'll see if I can dig up where it first appeared.
>
> Hmm, sorry for not specifying this upfront, but this failure is on Linux. ;-)
Ah, that's helpful to know.
> (Linux is my main platform, but I like to keep cygwin working because it has
> kept me sane on Windows ever since (about) 1995 ...)
> "Stranger in a strange land" ;-)
I used a different trick around the same time to keep me sane from
Windows, but I think it involved "dd" and "/dev/zero"...
> I'm using perl v5.8.8 on Linux.
Yeah, that is the problem. Calling localtime_r repeatedly while changing
the timezone does not work on some platforms:
https://rt.perl.org/rt3/Public/Bug/Display.html?id=26136
The fix (to call tzset each time) went into perl 5.10.0.
> > Ramsay, what happens with this patch on top?
>
> This patch fixes the test for me.
Great. I was guessing blindly when I wrote it, but having seen the perl
bug above, it all makes sense.
We should probably wrap it. I'm planning to queue this on top of Chris's
patch:
-- >8 --
Subject: [PATCH] cvsimport: work around perl tzset issue
On many platforms, the first invocation of localtime_r will
check $TZ in the environment, but subsequent invocations
will use a cache value. That means that setting $ENV{TZ} in
the middle of the program may or may not have an effect on
later calls to localtime. Perl 5.10.0 and later handles
this automatically for us, but we try to remain portable
back to 5.8. Work around it by calling tzset ourselves.
Signed-off-by: Jeff King <peff@peff.net>
---
git-cvsimport.perl | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index ceb119d..0a31ebd 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -24,11 +24,11 @@ use File::Basename qw(basename dirname);
use Time::Local;
use IO::Socket;
use IO::Pipe;
-use POSIX qw(strftime dup2 ENOENT);
+use POSIX qw(strftime tzset dup2 ENOENT);
use IPC::Open2;
$SIG{'PIPE'}="IGNORE";
-$ENV{'TZ'}="UTC";
+set_timezone('UTC');
our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r, $opt_R);
my (%conv_author_name, %conv_author_email, %conv_author_tz);
@@ -99,6 +99,15 @@ sub write_author_info($) {
close ($f);
}
+# Versions of perl before 5.10.0 may not automatically check $TZ each
+# time localtime is run (most platforms will do so only the first time).
+# We can work around this by using tzset() to update the internal
+# variable whenever we change the environment.
+sub set_timezone {
+ $ENV{TZ} = shift;
+ tzset();
+}
+
# convert getopts specs for use by git config
my %longmap = (
'A:' => 'authors-file',
@@ -854,9 +863,9 @@ sub commit {
}
}
- $ENV{'TZ'}=$author_tz;
+ set_timezone($author_tz);
my $commit_date = strftime("%s %z", localtime($date));
- $ENV{'TZ'}="UTC";
+ set_timezone('UTC');
$ENV{GIT_AUTHOR_NAME} = $author_name;
$ENV{GIT_AUTHOR_EMAIL} = $author_email;
$ENV{GIT_AUTHOR_DATE} = $commit_date;
--
1.8.0.207.gdf2154c
^ permalink raw reply related
* Re: [msysGit] Re: Git for Windows and line endings
From: Raja R Harinath @ 2012-11-04 12:37 UTC (permalink / raw)
To: git; +Cc: msysgit
In-Reply-To: <CADKp0pxuFsSEeZoeemyaqhSJEcsjj1arEOsF4Ub8=76y7tkwHg@mail.gmail.com>
Hi,
Chris B <chris.blaszczynski@gmail.com> writes:
[snip]
> - Windows has been able to cope with UNIX line endings a long time; no
> developer is using a default Notepad to open files with high
> expectations. Any Windows development tool and editor worth anything
> I've used is able to handle both just fine.
> - VIM also handles Windows line endings just fine as well. I just
> tested it on a Linux machine. Maybe old version? (pure VI is not even
> on this machine but hard to press these days it can't handle it.)
> - The files in .git folder are in UNIX format anyway, so why are those
> not also included in line ending changes? Isn't is because there is a
> Windows app (msysgit) running on Windows that expects the UNIX line
> ending? So in the same manor, someone might have a Windows system
> using some Cygwin components perhaps, or a Windows C program possibly
> poorly written or just old, that demand some text files to be left
> alone in the format we saved it.
There are several subtleties in LF handling with mixed systems. Here's
my write-up in:
https://github.com/mono/mono/blob/master/.gitattributes
for an example set of trade-offs. Quoting in full since it's fairly short.
- Hari
# CRLF Handling
# -------------
#
# The ideal situation would be to do no EOL normalization. Each file
# would have a default EOL, and tools on Windows and Linux would handle
# both EOL formats.
#
# We're not in the ideal world. A popular editor on Windows (possibly
# Visual Studio) silently introduces EOL corruption -- it displays an
# LF-file normally, but any newly added lines have CRLF. On Linux,
# Emacs and versions of VI handle LF-files and CRLF-files properly.
# However, emacs doesn't like files with both LF and CRLF EOLs. Editing
# the file without additional action will increase the EOL corruption
# in the file.
#
# Another vector for mixed EOLs is scripts. We mostly don't have scripts
# that add new lines -- so we rarely see this. However, one major event
# in the tree was the addition of copyright headers using a script. That
# script introduced EOL corruption.
#
# Any automated EOL normalization of files already in the repository will
# cause difficulties in traversing histories, assigning blame, etc. So, we
# don't want to change what's in the repository significantly, even if it
# causes trouble.
#
# What we do now:
#
# a) we ensure that there's no further corruption of LF-files. So, we use
# git's 'crlf' attribute on those files to ensure that things are fine
# when we work on Windows. We could use 'crlf=input', but it doesn't buy
# us much -- we might as well be working with consistent EOLs for files in
# working directories as well as in the repository
#
# b) if the file already of CRLFs, we don't do any normalization. We use '-crlf'
# so that git doesn't do any EOL-conversion of the file. As I said, this
# is mostly harmless on Linux. We can't mark these files as 'crlf' or use
# the new (git 1.7.2) 'eol=crlf' attribute, since it changes the contents
# _inside_ the repository [1], and hence makes history traversal annoying.
# So, we live with occasional EOL corruption.
#
# c) We can handle mixed-EOL files on a case-by-case basis, converting them to
# LF- or CRLF-files based on which causes fewer lines to change
#
# d) We try to ensure no further headaches, by declaring EOL normalization on
# code files, and Unix-flavoured files, like shell-scripts, makefiles, etc.
#
# [1] GIT use LFs as the normalized internal representation.
^ permalink raw reply
* Re: [PATCH] Add rm to submodule command.
From: Jeff King @ 2012-11-04 13:43 UTC (permalink / raw)
To: Alex Linden Levy; +Cc: Jens Lehmann, gitster, git
In-Reply-To: <1351877171-3176-1-git-send-email-lindenle@gmail.com>
On Fri, Nov 02, 2012 at 10:26:11AM -0700, Alex Linden Levy wrote:
> This change removes the config entries in .gitmodules and adds it.
> ---
Signoff?
> git-submodule.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 61 insertions(+), 1 deletion(-)
No documentation or tests?
> diff --git a/git-submodule.sh b/git-submodule.sh
> index ab6b110..29d950f 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
I'd defer to submodule experts on whether the steps to 'rm' the
submodule make sense. Jens?
-Peff
^ permalink raw reply
* Re: [PATCH] gitweb.perl: fix %highlight_ext
From: Jeff King @ 2012-11-04 13:45 UTC (permalink / raw)
To: rh; +Cc: git
In-Reply-To: <20121102141809.caf5cbc07f08769fd6a302ad@lavabit.com>
On Fri, Nov 02, 2012 at 02:18:09PM -0700, rh wrote:
> > I think the patch itself looks OK, but:
> >
> > 1. It isn't formatted to apply with git-am. Please use
> > git-format-patch.
>
> git format-patch command wouldn't work for me. I can see that you
> don't need more stuff to do but not knowing git I couldn't find the
> correct incantation to do this part. A problem with the files not
> being in a git repo I think. I'll spare you details.
The usual procedure is:
1. hack hack hack
2. git commit
3. git format-patch
And if you are not in a git repo, step 0 is "git init". :)
-Peff
^ permalink raw reply
* Re: [PATCH] gitweb.perl: fix %highlight_ext mappings
From: Jeff King @ 2012-11-04 13:48 UTC (permalink / raw)
To: rh; +Cc: git
In-Reply-To: <20121102141226.643a96e61b8bf383428c5287@lavabit.com>
On Fri, Nov 02, 2012 at 02:12:26PM -0700, rh wrote:
> The previous change created a dictionary of one-to-one elements when
> the intent was to map mutliple related types to one main type.
> e.g. bash, ksh, zsh, sh all map to sh since they share similar syntax
> This makes the mapping as the original change intended.
>
> Signed-off-by: rh <richard_hubbe11@lavabit.com>
>
> diff --git a/gitweb.cgi.orig b/gitweb.cgi
> index 060db27..155b238 100755
> --- a/gitweb.cgi.orig
> +++ b/gitweb.cgi
Close on the format. There should be a "---" after the sign-off but
before the diff. I can fix it up locally (and the patch looks good to
me).
However, one final thing: the point of the sign-off is to indicate that
you are legally OK to release the code under the DCO. For that reason,
we usually require a real name (not rh). I can guess at your real name
from your email, but I'd rather be sure. Can you provide it?
-Peff
^ permalink raw reply
* Re: [PATCH] Add rm to submodule command.
From: Jens Lehmann @ 2012-11-04 14:29 UTC (permalink / raw)
To: Jeff King; +Cc: Alex Linden Levy, gitster, git, Heiko Voigt
In-Reply-To: <20121104134324.GA31623@sigill.intra.peff.net>
Am 04.11.2012 14:43, schrieb Jeff King:
> On Fri, Nov 02, 2012 at 10:26:11AM -0700, Alex Linden Levy wrote:
>
>> This change removes the config entries in .gitmodules and adds it.
>> ---
>
> Signoff?
>
>> git-submodule.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 61 insertions(+), 1 deletion(-)
>
> No documentation or tests?
>
>> diff --git a/git-submodule.sh b/git-submodule.sh
>> index ab6b110..29d950f 100755
>> --- a/git-submodule.sh
>> +++ b/git-submodule.sh
>
> I'd defer to submodule experts on whether the steps to 'rm' the
> submodule make sense. Jens?
Hmm, this change adds the --quiet and --branch options to rm
which aren't used (and at least --branch makes no sense to me
here). Remainders of copy & paste? It also only affects the
.gitmodules setting and leaves the submodules work tree alone,
while I think it should - at least optionally - remove the work
tree just like "git rm" removes files too (of course only if
there is no .git directory found in it and no modifications are
present, as that would possibly lose data).
Me also thinks such a command should use my recent rm submodule
work to remove the work tree (found in your current master and
Junio's next branch), which does all necessary checks before it
removes the work tree together with the index entry. This could
be tweaked via a --cached option or such if the user wants to
keep the work tree.
But apart from those issues I'm not convinced that adding a
"git submodule rm" command is the best option. While working on
teaching "git mv" to move submodules I came to the conclusion
that it might be a better solution to let "git rm" remove the
submodule entry from the .gitmodules file itself (but of course
only if that file is found and contains such an entry, if not
it will silently do nothing to not disturb submodule users who
don't have a .gitmodules file and are using plain gitlinks).
The reason is that git core commands like status, diff and
fetch already use the path -> name mapping found in .gitmodules
and will behave strange when this is out of sync with the work
tree. So I strongly believe that doing a "git mv" should change
the path -> name mapping in .gitmodules too while moving the
submodule's work tree and updating the index (of course again
only if .gitmodules is found and contains such an entry, if not
it'll just move the work tree and update the index). Then we
won't need a new "git submodule mv" command as everything is
done inside the mv command. And for consistency I think "git rm"
should also remove the path -> name mapping (even though that is
not required for a rm to do its job, as no one will use that
setting later when the submodule is gone from the index). Then
we won't need a new "git submodule rm" at all.
Does that make sense?
^ permalink raw reply
* git-archive submodule support
From: Rotem Yaari @ 2012-11-04 14:53 UTC (permalink / raw)
To: git
Hi,
I was wondering if there are any plans to support inclusion of
submodules in git-archive. This is very useful for quickly preparing
ready-to-deploy archives of "unstable" branches etc., without the
users' need to clone submodule dependencies each time.
Is this planned at some point? Such a change would be greatly appreciated.
Thanks,
--
Rotem
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox