* [PATCH 2/3] cached-sha1-map: refactoring hash traversal code
From: Geoffrey Irving @ 2008-07-09 3:56 UTC (permalink / raw)
To: Johannes Schindelin, git@vger.kernel.org, Junio C Hamano
>From c4e60c28fe66985ac8224da832589c982010744e Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <irving@naml.us>
Date: Tue, 8 Jul 2008 19:47:22 -0700
Subject: [PATCH 2/3] cached-sha1-map: refactoring hash traversal code
Pulling common code from get_cached_sha1_entry and set_cached_sha1_entry
into static find_helper function.
---
cached-sha1-map.c | 68 +++++++++++++++++++++++++++++-----------------------
1 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/cached-sha1-map.c b/cached-sha1-map.c
index e363745..147c7a2 100644
--- a/cached-sha1-map.c
+++ b/cached-sha1-map.c
@@ -129,10 +129,14 @@ static size_t get_hash_index(const unsigned char *sha1)
return ntohl(*(size_t*)sha1);
}
-int get_cached_sha1_entry(struct cached_sha1_map *cache,
- const unsigned char *key, unsigned char *value)
+/*
+ * Returns the index if the entry exists, and the complemented index of
+ * the next free entry otherwise.
+ */
+static long find_helper(struct cached_sha1_map *cache,
+ const unsigned char *key)
{
- size_t i, mask;
+ long i, mask;
if (!cache->initialized)
init_cached_sha1_map(cache);
@@ -140,43 +144,47 @@ int get_cached_sha1_entry(struct cached_sha1_map *cache,
mask = cache->size - 1;
for (i = get_hash_index(key) & mask; ; i = (i+1) & mask) {
- if (!hashcmp(key, cache->entries[i].key)) {
- hashcpy(value, cache->entries[i].value);
- return 0;
- } else if (is_null_sha1(cache->entries[i].key))
- return -1;
+ if (!hashcmp(key, cache->entries[i].key))
+ return i;
+ else if (is_null_sha1(cache->entries[i].key))
+ return ~i;
}
}
+int get_cached_sha1_entry(struct cached_sha1_map *cache,
+ const unsigned char *key, unsigned char *value)
+{
+ long i = find_helper(cache, key);
+ if(i < 0)
+ return -1;
+
+ /* entry found, return value */
+ hashcpy(value, cache->entries[i].value);
+ return 0;
+}
+
void set_cached_sha1_entry(struct cached_sha1_map *cache,
const unsigned char *key, const unsigned char *value)
{
- size_t i, mask;
+ long i;
struct cached_sha1_entry *entry;
- if (!cache->initialized)
- init_cached_sha1_map(cache);
-
- if (4*cache->count >= 3*cache->size)
- grow_map(cache);
-
- mask = cache->size - 1;
-
- for (i = get_hash_index(key) & mask; ; i = (i+1) & mask) {
- entry = cache->entries+i;
-
- if (is_null_sha1(entry->key)) {
- hashcpy(entry->key, key);
+ i = find_helper(cache, key);
+
+ if (i < 0) { /* write new entry */
+ entry = cache->entries + ~i;
+ hashcpy(entry->key, key);
+ hashcpy(entry->value, value);
+ cache->count++;
+ cache->dirty = 1;
+ } else { /* overwrite existing entry */
+ entry = cache->entries + i;
+ if (hashcmp(value, entry->value)) {
hashcpy(entry->value, value);
- cache->count++;
cache->dirty = 1;
- return;
- } else if(!hashcmp(key, entry->key)) {
- if (hashcmp(value, entry->value)) {
- hashcpy(entry->value, value);
- cache->dirty = 1;
- }
- return;
}
}
+
+ if (4*cache->count >= 3*cache->size)
+ grow_map(cache);
}
--
1.5.6.2.258.g7a51a
^ permalink raw reply related
* [PATCH 1/3] cherry: cache patch-ids to avoid repeating work
From: Geoffrey Irving @ 2008-07-09 3:53 UTC (permalink / raw)
To: Johannes Schindelin, git@vger.kernel.org, Junio C Hamano
>From a3afd1455d215a541e1481e0f064df743d9219cc Mon Sep 17 00:00:00 2001
From: Geoffrey Irving <irving@naml.us>
Date: Sat, 7 Jun 2008 16:03:49 -0700
Subject: [PATCH 1/3] cherry: cache patch-ids to avoid repeating work
Added cached-sha-map.[hc] implementing a persistent hash map from sha1 to
sha1. The map is read with mmap, and completely rewritten if any entries
change. It would be good to add incremental update to handle the usual case
where only a few entries change.
This structure is used by patch-ids.c to cache the mapping from commit to
patch-id into $GIT_DIR/patch-id-cache. In the one case I've tested so far,
this speeds up the second invocation of git-cherry by two orders of
magnitude.
Original code cannibalized from Johannes Schindelin's notes-index structure.
---
Here's another (hopefully final) version of the patch-id-cache code,
since I finally got around to updating it with Dscho's suggestions.
Makefile | 2 +
cached-sha1-map.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++
cached-sha1-map.h | 45 +++++++++++++
patch-ids.c | 18 +++++-
4 files changed, 246 insertions(+), 1 deletions(-)
create mode 100644 cached-sha1-map.c
create mode 100644 cached-sha1-map.h
diff --git a/Makefile b/Makefile
index 4796565..f7360e1 100644
--- a/Makefile
+++ b/Makefile
@@ -356,6 +356,7 @@ LIB_H += pack-refs.h
LIB_H += pack-revindex.h
LIB_H += parse-options.h
LIB_H += patch-ids.h
+LIB_H += cached-sha1-map.h
LIB_H += path-list.h
LIB_H += pkt-line.h
LIB_H += progress.h
@@ -436,6 +437,7 @@ LIB_OBJS += pager.o
LIB_OBJS += parse-options.o
LIB_OBJS += patch-delta.o
LIB_OBJS += patch-ids.o
+LIB_OBJS += cached-sha1-map.o
LIB_OBJS += path-list.o
LIB_OBJS += path.o
LIB_OBJS += pkt-line.o
diff --git a/cached-sha1-map.c b/cached-sha1-map.c
new file mode 100644
index 0000000..e363745
--- /dev/null
+++ b/cached-sha1-map.c
@@ -0,0 +1,182 @@
+#include "cached-sha1-map.h"
+
+union cached_sha1_map_header {
+ struct {
+ char signature[4]; /* HASH */
+ off_t count, size;
+ };
+ struct cached_sha1_entry padding; /* pad header out to 40 bytes */
+};
+
+static const char *signature = "HASH";
+
+static void init_empty_map(struct cached_sha1_map *cache, size_t size)
+{
+ cache->count = 0;
+ cache->size = size;
+ cache->initialized = 1;
+ cache->dirty = 1;
+ cache->mmapped = 0;
+ cache->entries = xcalloc(size, sizeof(struct cached_sha1_entry));
+}
+
+static void grow_map(struct cached_sha1_map *cache)
+{
+ struct cached_sha1_map new_cache;
+ size_t i;
+
+ /* allocate cache with twice the size */
+ new_cache.filename = cache->filename;
+ init_empty_map(&new_cache, cache->size * 2);
+
+ /* reinsert all entries */
+ for (i = 0; i < cache->size; i++)
+ if (!is_null_sha1(cache->entries[i].key))
+ set_cached_sha1_entry(&new_cache,
+ cache->entries[i].key, cache->entries[i].value);
+ /* finish */
+ free_cached_sha1_map(cache);
+ *cache = new_cache;
+}
+
+static void init_cached_sha1_map(struct cached_sha1_map *cache)
+{
+ int fd;
+ union cached_sha1_map_header header;
+
+ if (cache->initialized)
+ return;
+
+ fd = open(git_path(cache->filename), O_RDONLY);
+ if (fd < 0) {
+ init_empty_map(cache, 64);
+ return;
+ }
+
+ if (read_in_full(fd, &header, sizeof(header)) != sizeof(header))
+ die("cannot read %s header", cache->filename);
+
+ if (memcmp(header.signature, signature, 4))
+ die("%s has invalid header", cache->filename);
+
+ if (header.size & (header.size-1))
+ die("%s size %lld is not a power of two", cache->filename,
+ (long long)header.size);
+
+ cache->count = header.count;
+ cache->size = header.size;
+ cache->dirty = 0;
+ cache->initialized = 1;
+ cache->mmapped = 1;
+
+ /* check off_t to size_t conversion */
+ if (cache->count != header.count || cache->size != header.size)
+ die("%s is too large to hold in memory", cache->filename);
+
+ /* mmap entire file so that file / memory blocks are aligned */
+ cache->entries = xmmap(NULL,
+ sizeof(struct cached_sha1_entry) * (header.size + 1),
+ PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ cache->entries += 1; /* skip header */
+ close(fd);
+}
+
+int write_cached_sha1_map(struct cached_sha1_map *cache)
+{
+ union cached_sha1_map_header header;
+ struct lock_file update_lock;
+ int fd;
+ size_t entry_size;
+
+ if (!cache->initialized || !cache->dirty)
+ return 0;
+
+ fd = hold_lock_file_for_update(&update_lock,
+ git_path(cache->filename), 0);
+
+ if (fd < 0)
+ return error("could not construct %s", cache->filename);
+
+ memcpy(header.signature, signature, 4);
+ header.count = cache->count;
+ header.size = cache->size;
+ entry_size = sizeof(struct cached_sha1_entry) * cache->size;
+ if (write_in_full(fd, &header, sizeof(header)) != sizeof(header)
+ || write_in_full(fd, cache->entries, entry_size) != entry_size)
+ return error("could not write %s", cache->filename);
+
+ if (commit_lock_file(&update_lock) < 0)
+ return error("could not write %s", cache->filename);
+
+ cache->dirty = 0;
+ return 0;
+}
+
+void free_cached_sha1_map(struct cached_sha1_map *cache)
+{
+ if (!cache->initialized)
+ return;
+
+ if (cache->mmapped)
+ munmap(cache->entries - 1,
+ sizeof(struct cached_sha1_entry) * (cache->size + 1));
+ else
+ free(cache->entries);
+}
+
+static size_t get_hash_index(const unsigned char *sha1)
+{
+ return ntohl(*(size_t*)sha1);
+}
+
+int get_cached_sha1_entry(struct cached_sha1_map *cache,
+ const unsigned char *key, unsigned char *value)
+{
+ size_t i, mask;
+
+ if (!cache->initialized)
+ init_cached_sha1_map(cache);
+
+ mask = cache->size - 1;
+
+ for (i = get_hash_index(key) & mask; ; i = (i+1) & mask) {
+ if (!hashcmp(key, cache->entries[i].key)) {
+ hashcpy(value, cache->entries[i].value);
+ return 0;
+ } else if (is_null_sha1(cache->entries[i].key))
+ return -1;
+ }
+}
+
+void set_cached_sha1_entry(struct cached_sha1_map *cache,
+ const unsigned char *key, const unsigned char *value)
+{
+ size_t i, mask;
+ struct cached_sha1_entry *entry;
+
+ if (!cache->initialized)
+ init_cached_sha1_map(cache);
+
+ if (4*cache->count >= 3*cache->size)
+ grow_map(cache);
+
+ mask = cache->size - 1;
+
+ for (i = get_hash_index(key) & mask; ; i = (i+1) & mask) {
+ entry = cache->entries+i;
+
+ if (is_null_sha1(entry->key)) {
+ hashcpy(entry->key, key);
+ hashcpy(entry->value, value);
+ cache->count++;
+ cache->dirty = 1;
+ return;
+ } else if(!hashcmp(key, entry->key)) {
+ if (hashcmp(value, entry->value)) {
+ hashcpy(entry->value, value);
+ cache->dirty = 1;
+ }
+ return;
+ }
+ }
+}
diff --git a/cached-sha1-map.h b/cached-sha1-map.h
new file mode 100644
index 0000000..f592d07
--- /dev/null
+++ b/cached-sha1-map.h
@@ -0,0 +1,45 @@
+#ifndef CACHED_SHA1_MAP_H
+#define CACHED_SHA1_MAP_H
+
+#include "cache.h"
+
+/*
+ * A cached-sha1-map is a file storing a hash map from sha1 to sha1.
+ *
+ * The file is mmap'ed, updated in memory during operation, and flushed
+ * back to disk when freed. Currently the entire file is rewritten for
+ * any change. This could be a significant bottleneck for common uses,
+ * so it would be good to fix this later if possible.
+ *
+ * The performance of a hash map depends highly on a good hashing
+ * algorithm, to avoid collisions. Lucky us! SHA-1 is a pretty good
+ * hashing algorithm.
+ */
+
+struct cached_sha1_entry {
+ unsigned char key[20];
+ unsigned char value[20];
+};
+
+struct cached_sha1_map {
+ const char *filename; /* relative to GIT_DIR */
+
+ /* rest is for internal use */
+ size_t count, size;
+ unsigned int initialized : 1;
+ unsigned int dirty : 1;
+ unsigned int mmapped : 1;
+ struct cached_sha1_entry *entries; /* pointer to mmap'ed memory + 1 */
+};
+
+extern int get_cached_sha1_entry(struct cached_sha1_map *cache,
+ const unsigned char *key,unsigned char *value);
+
+extern void set_cached_sha1_entry(struct cached_sha1_map *cache,
+ const unsigned char *key, const unsigned char *value);
+
+extern int write_cached_sha1_map(struct cached_sha1_map *cache);
+
+extern void free_cached_sha1_map(struct cached_sha1_map *cache);
+
+#endif
diff --git a/patch-ids.c b/patch-ids.c
index 3be5d31..36332f3 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -2,17 +2,31 @@
#include "diff.h"
#include "commit.h"
#include "patch-ids.h"
+#include "cached-sha1-map.h"
+
+struct cached_sha1_map patch_id_cache;
static int commit_patch_id(struct commit *commit, struct diff_options *options,
unsigned char *sha1)
{
+ /* pull patch-id out of the cache if possible */
+ patch_id_cache.filename = "patch-id-cache";
+ if (!get_cached_sha1_entry(&patch_id_cache, commit->object.sha1, sha1))
+ return 0;
+
if (commit->parents)
diff_tree_sha1(commit->parents->item->object.sha1,
commit->object.sha1, "", options);
else
diff_root_tree_sha1(commit->object.sha1, "", options);
diffcore_std(options);
- return diff_flush_patch_id(options, sha1);
+ int ret = diff_flush_patch_id(options, sha1);
+ if (ret)
+ return ret;
+
+ /* record commit, patch-id pair in cache */
+ set_cached_sha1_entry(&patch_id_cache, commit->object.sha1, sha1);
+ return 0;
}
static uint32_t take2(const unsigned char *id)
@@ -136,6 +150,8 @@ int free_patch_ids(struct patch_ids *ids)
next = patches->next;
free(patches);
}
+
+ write_cached_sha1_map(&patch_id_cache);
return 0;
}
--
1.5.6.2.258.g7a51a
^ permalink raw reply related
* Re: git push to amazon s3 [was: [GSoC] What is status of Git's Google Summer of Code 2008 projects?]
From: Shawn O. Pearce @ 2008-07-09 3:26 UTC (permalink / raw)
To: Mike Hommey
Cc: Tarmigan, Marek Zawirski, git, Daniel Barkalow, Nick Hengeveld,
Johannes Schindelin
In-Reply-To: <20080708055610.GA12591@glandium.org>
Mike Hommey <mh@glandium.org> wrote:
> FWIW, I'm starting to work again on the http backend overhaul. My idea
> is to provide a generic dumb protocol vfs-like interface, so that other
> dumb protocols could be built out of it.
jgit has a vfs abstraction for the different dumb protocols. Not sure
if you would find it of any value to read as we are also able to use a
number of Java standard abstractions like InputStream/OutputStream,
but here it is:
WalkRemoteObjectDatabase:
http://repo.or.cz/w/egit.git?a=blob;f=org.spearce.jgit/src/org/spearce/jgit/transport/WalkRemoteObjectDatabase.java;h=915faac9eb85e59c0ed2c08b9631d03cbc4c6bf8;hb=8d085723b260f3b51a70d11b723608779160b090
Thus far this abstraction has worked for sftp:// and amazon-s3://.
WebDAV may make it more complicated due to locking being available
(and something we would want to use to protect writes) but S3 uses
HTTP PUT much like DAV does to upload content so there wouldn't be
too many changes to actually implement DAV support.
--
Shawn.
^ permalink raw reply
* Re: git push to amazon s3 [was: [GSoC] What is status of Git's Google Summer of Code 2008 projects?]
From: Shawn O. Pearce @ 2008-07-09 3:22 UTC (permalink / raw)
To: Tarmigan
Cc: Marek Zawirski, git, Daniel Barkalow, Nick Hengeveld,
Johannes Schindelin
In-Reply-To: <905315640807072248w44ccdc4y2f1cf54a10c50c43@mail.gmail.com>
Tarmigan <tarmigan+git@gmail.com> wrote:
> (trimmed cc list to folks who've touched http-push.c)
> On Mon, Jul 7, 2008 at 9:19 PM, Shawn O. Pearce <spearce@spearce.org> wrote:
> > Using Marek's pack generation code I added support for push over
> > the dumb sftp:// and amazon-s3:// protocols, with the latter also
> > supporting transparent client side encryption.
>
> Can you describe the s3 support that you added? Did you do any
> locking when you pushed? The objects and packs seem likely to be
> naturally OK, but I was worried about refs/ and especially
> objects/info/packs and info/refs (fetch over http works currently out
> of the box with publicly accessable s3 repos).
It behaves like http push does in C git in that it is pretty
transparent to the end-user:
# Create a bucket using other S3 tools.
# I used jets3t's cockpit tool to creat "gitney".
# Create a configuration file for jgit's S3 client:
#
$ touch ~/.jgit_s3_public
$ chmod 600 ~/.jgit_s3_public
$ cat >>~/.jgit_s3_public
accesskey: AWSAccessKeyId
secretkey: AWSSecretAccessKey
acl: public
EOF
# Configure the remote and push
#
$ git remote add s3 amazon-s3://.jgit_s3_public@gitney/projects/egit.git/
$ jgit push s3 refs/heads/master
$ jgit push --tags s3
# Future incremental updates are just as easy
#
$ jgit push s3 refs/heads/master
(or)
$ git config remote.s3.push refs/heads/master
$ jgit push s3
This is now cloneable[*1*]:
$ git clone http://gitney.s3.amazonaws.com/projects/egit.git
Pushes are incremental, rather than the approach you outlined, as
that causes a full re-upload of the repository. Consequently there
is relatively little bandwidth usage during subsequent pushes.
A jgit amazon-s3 URL is organized as:
amazon-s3://$config@$bucket/$prefix
where:
$config = path to configuration in $GIT_DIR/$config or $HOME/$config
$bucket = name of the Amazon S3 bucket holding the objects
$prefix = prefix to apply to all objects, implicitly ends in "/"
Amazon S3 atomically replaces a file, but offers no locking support.
Our crude remote VFS abstraction offers two types of file write
operations:
- Atomic write for small (in-memory) files <~1M
- Stream write for large (e.g. pack) files >~1M
In the S3 implementation both operations are basically the same
code, since even large streams are atomic updates. But in sftp://
our remote VFS writes to a "$path.lock" for the atomic case and
renames to "$path". This is not the same as a real lock, but it
avoids readers from seeing an in-progress update.
We are very carefully to order the update operations to try and
avoid any sorts of race conditions:
- Delete loose refs which are being deleted.
- Upload new pack:
- If same pack already exists:
- (atomic) Remove it from objects/info/packs
- Delete .idx
- Delete .pack
- Upload new .pack
- Upload new .idx
- (atomic) Add to front of objects/info/packs.
- (atomic) Create/update loose refs.
- (atomic) Update (if necessary) packed-refs.
- (atomic) Update info/refs.
Since we are pushing over a dumb transport we assume readers
are pulling over the same dumb transport and thus rely upon the
objects/info/packs and info/refs files to obtain the listing of
what is available. This isn't true though for jgit's sftp://
and amazon-s3:// protocols as both support navigation of the
objects/packs and refs/{heads,tags} tree directly.
Locking on S3 is difficult. Multi-object writes may not sync
across the S3 cluster immediately. This means you can write to A,
then to B, then read A and see the old content still there, then
seconds later read A again and see the new content suddenly arrive.
It all depends upon when the replicas update and which replica
the load-balancer sends you into during the request. So despite
our attempts to order writes to S3 it is still possible for an S3
write to appear "late" and for a client to see a ref in info/refs
for which the corresponding pack is not listed in object/info/packs.
However, this is the same mirroring problem that kernel.org has for
its git trees. I believe they are moved out to the public mirrors
by dumb rsync and not some sort of smart git-aware transport.
As rsync is free to order the writes out of order kernel.org has
the same issue. ;-)
Actually I suspect the S3 replica update occurs more quickly than
the kernel.org mirrors update, so the window under which a client
can see out-of-order writes is likely smaller.
*1* You need a bug fix in jgit to correctly initialize HEAD during
push to a new, non-existant repository stored on S3. The patch
is going to be posted later this evening, its still in my tree.
--
Shawn.
^ permalink raw reply
* Re: [PATCH 2/4] git-imap-send: Add support for SSL.
From: Abhijit Menon-Sen @ 2008-07-09 2:28 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Robert Shearman, git
In-Reply-To: <7vbq18q7yk.fsf@gitster.siamese.dyndns.org>
At 2008-07-08 16:20:19 -0700, gitster@pobox.com wrote:
>
> > - Port = 143
> > + Port = 993
> > + sslverify = false
> > ..........................
>
> Don't we also want to keep a vanilla configuration in the example, or
> is imaps the norm and unencrypted imap is exception these days?
The norm is IMAP+STARTTLS on port 143, not IMAPS on port 993. The latter
is also widely deployed for compatibility with older clients, but it is
non-standard and its use isn't exactly encouraged.
-- ams
^ permalink raw reply
* [PATCH] git-svn: find-rev and rebase for SVN::Mirror repositories
From: João Abecasis @ 2008-07-09 2:08 UTC (permalink / raw)
To: git, Eric Wong
find-rev and rebase error out on svm because git-svn doesn't trace the original
svn revision numbers back to git commits. The updated test case, included in the
patch, shows the issue and passes with the rest of the patch applied.
This fixes Git::SVN::find_by_url to find branches based on the svm:source URL,
where useSvmProps is set. Also makes sure cmd_find_rev and working_head_info use
the information they have to correctly track the source repository. This is
enough to get find-rev and rebase working.
Signed-off-by: João Abecasis <joao@abecasis.name>
---
Incidentally, I've tried submitting these fixes before, but failed to
get much attention, so I could be doing something wrong... Any input
on the patch or my approach to this list is appreciated. This time I
reworded the commit message and added Eric Wong to the CC list, since
he seems to be Ack'ing git-svn patches.
Anyway, the patch does get things working for me.
Cheers,
João
git-svn.perl | 37 +++++++++++++++++++++++++++++++++----
t/t9110-git-svn-use-svm-props.sh | 9 +++++++++
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index a366c89..f5baec1 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -537,13 +537,13 @@ sub cmd_find_rev {
my $head = shift;
$head ||= 'HEAD';
my @refs;
- my (undef, undef, undef, $gs) = working_head_info($head, \@refs);
+ my (undef, undef, $uuid, $gs) = working_head_info($head, \@refs);
unless ($gs) {
die "Unable to determine upstream SVN information from ",
"$head history\n";
}
my $desired_revision = substr($revision_or_hash, 1);
- $result = $gs->rev_map_get($desired_revision);
+ $result = $gs->rev_map_get($desired_revision, $uuid);
} else {
my (undef, $rev, undef) = cmt_metadata($revision_or_hash);
$result = $rev;
@@ -1162,7 +1162,7 @@ sub working_head_info {
if (defined $url && defined $rev) {
next if $max{$url} and $max{$url} < $rev;
if (my $gs = Git::SVN->find_by_url($url)) {
- my $c = $gs->rev_map_get($rev);
+ my $c = $gs->rev_map_get($rev, $uuid);
if ($c && $c eq $hash) {
close $fh; # break the pipe
return ($url, $rev, $uuid, $gs);
@@ -1416,11 +1416,17 @@ sub fetch_all {
sub read_all_remotes {
my $r = {};
+ my $usesvmprops = eval { command_oneline(qw/config --bool
+ svn.useSvmProps/) };
+ $usesvmprops = $usesvmprops eq 'true' if $usesvmprops;
foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
if (m!^(.+)\.fetch=\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!) {
my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
$local_ref =~ s{^/}{};
$r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
+ $r->{$remote}->{svm} = {} if $usesvmprops;
+ } elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
+ $r->{$1}->{svm} = {};
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
$r->{$1}->{url} = $2;
} elsif (m!^(.+)\.(branches|tags)=
@@ -1437,6 +1443,21 @@ sub read_all_remotes {
}
}
}
+
+ map {
+ if (defined $r->{$_}->{svm}) {
+ my $svm;
+ eval {
+ my $section = "svn-remote.$_";
+ $svm = {
+ source => tmp_config('--get', "$section.svm-source"),
+ replace => tmp_config('--get', "$section.svm-replace"),
+ }
+ };
+ $r->{$_}->{svm} = $svm;
+ }
+ } keys %$r;
+
$r;
}
@@ -1563,13 +1584,21 @@ sub find_by_url { # repos_root and, path are optional
}
my $p = $path;
my $rwr = rewrite_root({repo_id => $repo_id});
+ my $svm = $remotes->{$repo_id}->{svm}
+ if defined $remotes->{$repo_id}->{svm};
unless (defined $p) {
$p = $full_url;
my $z = $u;
+ my $prefix = '';
if ($rwr) {
$z = $rwr;
+ } elsif (defined $svm) {
+ $z = $svm->{source};
+ $prefix = $svm->{replace};
+ $prefix =~ s#^\Q$u\E(?:/|$)##;
+ $prefix =~ s#/$##;
}
- $p =~ s#^\Q$z\E(?:/|$)## or next;
+ $p =~ s#^\Q$z\E(?=/|$)#$prefix# or next;
}
foreach my $f (keys %$fetch) {
next if $f ne $p;
diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh
index 047659f..04d2a65 100755
--- a/t/t9110-git-svn-use-svm-props.sh
+++ b/t/t9110-git-svn-use-svm-props.sh
@@ -49,4 +49,13 @@ test_expect_success 'verify metadata for /dir' "
grep '^git-svn-id: $dir_url@1 $uuid$'
"
+test_expect_success 'find commit based on SVN revision number' "
+ git-svn find-rev r12 |
+ grep `git rev-parse HEAD`
+ "
+
+test_expect_success 'empty rebase' "
+ git-svn rebase
+ "
+
test_done
--
1.5.6
^ permalink raw reply related
* Re: [PATCH 4/4] Documentation: Improve documentation for git-imap-send(1).
From: Brian Gernhardt @ 2008-07-09 1:35 UTC (permalink / raw)
To: Robert Shearman; +Cc: git
In-Reply-To: <1215555496-21335-4-git-send-email-robertshearman@gmail.com>
On Jul 8, 2008, at 6:18 PM, Robert Shearman wrote:
> +Using direct mode:
>
> +.........................
> [imap]
> - Host = imaps://imap.example.com
> - User = bob
> - Pass = pwd
> - Port = 993
> + folder = "[Gmail]/Drafts"
> + host = imaps://imap.example.com
> + user = bob
> + pass = p4ssw0rd
> + port = 123
> sslverify = false
> ..........................
If you're going to use [Gmail]/Drafts as the example folder, shouldn't
you just use mail.google.com as your example? Google themselves use username@gmail.com
as an example[1], so that should be safe. So:
..............................
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
port = 993
user = username
pass = password
..............................
And I also assume that someone has tried this with Gmail and it
doesn't mangle the Drafts. I'd also move the sslverify option into
the tunneling example, as it's more likely to be needed there.
[1] http://mail.google.com/support/bin/answer.py?answer=78799
~~ Brian
^ permalink raw reply
* Re: [PATCH 1/4] git-imap-send: Allow the program to be run from subdirectories of a git tree.
From: Jay Soffian @ 2008-07-09 1:28 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Robert Shearman, git
In-Reply-To: <7v3amjq2mj.fsf@gitster.siamese.dyndns.org>
On Tue, Jul 8, 2008 at 9:15 PM, Junio C Hamano <gitster@pobox.com> wrote:
> I thought Jeff already explained why this NULL was a bad idea, but perhaps
> I was dreaming...
http://article.gmane.org/gmane.comp.version-control.git/87701
j.
^ permalink raw reply
* [PATCH 2/2] branch --merged/--not-merged: allow specifying arbitrary commit
From: Junio C Hamano @ 2008-07-09 1:22 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git, Lars Hjemli
In-Reply-To: <7vvdzfoo1s.fsf@gitster.siamese.dyndns.org>
"git-branch --merged" is a handy way to list all the branches that have
already been merged to the current branch, but it did not allow checking
against anything but the current branch. Having to check out only for
that purpose made the command practically useless.
This updates the option parser so that "git branch --merged next" is
accepted when you are on 'master' branch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* This does have an issue. --no-<option>=<value> is often nonsense and
parse-options does not accept it (and I do not think we would want to
change it). The use of "--no-merged" was a mistake, but nobody has
perfect foresight.
This adds --not-merged <commit> and allows the <commit> to default to
HEAD if not given to work it around. This and the previous one are not
for application but primarily meant for discussion on what further
flexibility we may want to have in parse-options.
builtin-branch.c | 50 ++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/builtin-branch.c b/builtin-branch.c
index 375e5e0..151f519 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -46,7 +46,12 @@ enum color_branch {
COLOR_BRANCH_CURRENT = 4,
};
-static int mergefilter = -1;
+static enum merge_filter {
+ NO_FILTER = 0,
+ SHOW_NOT_MERGED,
+ SHOW_MERGED,
+} merge_filter;
+static unsigned char merge_filter_ref[20];
static int parse_branch_color_slot(const char *var, int ofs)
{
@@ -234,13 +239,15 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
if ((kind & ref_list->kinds) == 0)
return 0;
- if (mergefilter > -1) {
+ if (merge_filter != NO_FILTER) {
branch.item = lookup_commit_reference_gently(sha1, 1);
if (!branch.item)
die("Unable to lookup tip of branch %s", refname);
- if (mergefilter == 0 && has_commit(head_sha1, &branch))
+ if (merge_filter == SHOW_NOT_MERGED &&
+ has_commit(merge_filter_ref, &branch))
return 0;
- if (mergefilter == 1 && !has_commit(head_sha1, &branch))
+ if (merge_filter == SHOW_MERGED &&
+ !has_commit(merge_filter_ref, &branch))
return 0;
}
@@ -421,6 +428,20 @@ static int opt_parse_with_commit(const struct option *opt, const char *arg, int
return 0;
}
+static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
+{
+ merge_filter = ((opt->long_name[0] == 'n')
+ ? SHOW_NOT_MERGED
+ : SHOW_MERGED);
+ if (unset)
+ merge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */
+ if (!arg)
+ arg = "HEAD";
+ if (get_sha1(arg, merge_filter_ref))
+ die("malformed object name %s", arg);
+ return 0;
+}
+
int cmd_branch(int argc, const char **argv, const char *prefix)
{
int delete = 0, rename = 0, force_create = 0;
@@ -461,7 +482,18 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"),
- OPT_SET_INT(0, "merged", &mergefilter, "list only merged branches", 1),
+ {
+ OPTION_CALLBACK, 0, "merged", &merge_filter_ref,
+ "commit", "print only merged branches",
+ PARSE_OPT_FAKELASTARG,
+ opt_parse_merge_filter, (intptr_t) "HEAD",
+ },
+ {
+ OPTION_CALLBACK, 0, "not-merged", &merge_filter_ref,
+ "commit", "print only not merged branches",
+ PARSE_OPT_FAKELASTARG,
+ opt_parse_merge_filter, (intptr_t) "HEAD",
+ },
OPT_END(),
};
@@ -471,9 +503,6 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
branch_use_color = git_use_color_default;
track = git_branch_track;
- argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
- if (!!delete + !!rename + !!force_create > 1)
- usage_with_options(builtin_branch_usage, options);
head = resolve_ref("HEAD", head_sha1, 0, NULL);
if (!head)
@@ -486,6 +515,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
die("HEAD not found below refs/heads!");
head += 11;
}
+ hashcpy(merge_filter_ref, head_sha1);
+
+ argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+ if (!!delete + !!rename + !!force_create > 1)
+ usage_with_options(builtin_branch_usage, options);
if (delete)
return delete_branches(argc, argv, delete > 1, kinds);
--
1.5.6.2.255.gbed62
^ permalink raw reply related
* [PATCH 1/2] branch --contains: default to HEAD
From: Junio C Hamano @ 2008-07-09 1:17 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git, Lars Hjemli
In-Reply-To: <7vvdzfoo1s.fsf@gitster.siamese.dyndns.org>
We used to require the name of the commit to limit the branches shown to
the --contains option, but more recent --merged/--no-meregd defaults to
HEAD (and they do not allow arbitrary commit, which is a separate issue).
This teaches --contains to default to HEAD when no parameter is given.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* This comes on top of the FAKELASTARG patch
builtin-branch.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/builtin-branch.c b/builtin-branch.c
index d279702..375e5e0 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -438,13 +438,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches",
REF_REMOTE_BRANCH),
- OPT_CALLBACK(0, "contains", &with_commit, "commit",
- "print only branches that contain the commit",
- opt_parse_with_commit),
+ {
+ OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
+ "print only branches that contain the commit",
+ PARSE_OPT_FAKELASTARG,
+ opt_parse_with_commit, (intptr_t)"HEAD",
+ },
{
OPTION_CALLBACK, 0, "with", &with_commit, "commit",
"print only branches that contain the commit",
- PARSE_OPT_HIDDEN, opt_parse_with_commit,
+ PARSE_OPT_HIDDEN | PARSE_OPT_FAKELASTARG,
+ opt_parse_with_commit, (intptr_t) "HEAD",
},
OPT__ABBREV(&abbrev),
--
1.5.6.2.255.gbed62
^ permalink raw reply related
* Re: [PATCH] parse-options: add PARSE_OPT_FAKELASTARG flag.
From: Junio C Hamano @ 2008-07-09 1:15 UTC (permalink / raw)
To: Pierre Habouzit; +Cc: git, Lars Hjemli
In-Reply-To: <20080708103408.GC19202@artemis.madism.org>
Pierre Habouzit <madcoder@debian.org> writes:
> If you set this for a given flag, and the flag appears without a value on
> the command line, then the `defval' is used to fake a new argument.
>
> Note that this flag is meaningless in presence of OPTARG or NOARG flags.
> (in the current implementation it will be ignored, but don't rely on it).
>
> Signed-off-by: Pierre Habouzit <madcoder@debian.org>
> ---
>
> > (3) inspired from (1) and (2), have a flag for options that says
> > "I do take an argument, but if I'm the last option on the
> > command line, please fake this argument for me.
> >
> > I really like (3) more FWIW as it doesn't generate ambiguous
> > parsers like (2) would, and it's not horrible like (1). And cherry
> > on top it's pretty trivial to implement I think.
Yeah, I do not particularly want a major rewrite that only introduces
possible ambiguity to the option parser (even though arguably it would add
to the usability very much, just like we accept revs and paths when
unambiguous), so I think this is a reasonable compromise.
It feels more like LASTARG_DEFAULT but that is bikeshedding ;-)
But I see one thinko (fix below) and another issue I am not sure what the
best fix would be.
---
diff --git a/parse-options.c b/parse-options.c
index b6735a5..cba20d7 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -26,11 +26,11 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
if (p->opt) {
*arg = p->opt;
p->opt = NULL;
+ } else if (p->argc == 1 && (opt->flags & PARSE_OPT_FAKELASTARG)) {
+ *arg = (const char *)opt->defval;
} else if (p->argc) {
p->argc--;
*arg = *++p->argv;
- } else if (opt->flags & PARSE_OPT_FAKELASTARG) {
- *arg = (const char *)opt->defval;
} else
return opterror(opt, "requires a value", flags);
return 0;
^ permalink raw reply related
* Re: [PATCH 1/4] git-imap-send: Allow the program to be run from subdirectories of a git tree.
From: Junio C Hamano @ 2008-07-09 1:15 UTC (permalink / raw)
To: Robert Shearman; +Cc: git
In-Reply-To: <1215555496-21335-1-git-send-email-robertshearman@gmail.com>
Robert Shearman <robertshearman@gmail.com> writes:
> Call setup_git_directory_gently to allow git-imap-send to be used from subdirectories of a git tree.
> ---
> imap-send.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/imap-send.c b/imap-send.c
> index 1ec1310..89a1532 100644
> --- a/imap-send.c
> +++ b/imap-send.c
> @@ -1296,6 +1296,7 @@ main(int argc, char **argv)
> /* init the random number generator */
> arc4_init();
>
> + setup_git_directory_gently( NULL );
> git_config(git_imap_config, NULL);
>
> if (!imap_folder) {
I thought Jeff already explained why this NULL was a bad idea, but perhaps
I was dreaming...
Besides, the extra spaces around the argument is very distracting.
^ permalink raw reply
* Re: Git, merging, and News/Relnotes files
From: Edward Z. Yang @ 2008-07-09 1:14 UTC (permalink / raw)
To: git; +Cc: dpotapov, torvalds, pdebie
In-Reply-To: <37fcd2780807060753h26d9391crff5f9ba5531db654@mail.gmail.com>
Dmitry Potapov wrote:
> Having one file changed on almost every commit is not a good idea, and
> not only because it will cause unnecessary conflicts but also it may
> considerable increase the size of the whole repository. By default, the
> delta compression has limit 50, which means that every 50 change of file
> will become its full copy. If the changelog file is changed very often
> and it is long, it may turn out that changelog alone takes as much space
> as the rest of the source tree.
That is certainly a good technical point, and I will certainly look into
building a log parser after we wrap up our next release cycle.
P.S. Linus, we ended up manually merging the NEWS file; in some cases
there were branch specific changes in the file which would have been
completely inappropriate with a union merge. Thank you for the
suggestion, however.
^ permalink raw reply
* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
From: Junio C Hamano @ 2008-07-09 1:09 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Stephan Beyer, git
In-Reply-To: <alpine.DEB.1.00.0807090230560.5277@eeepc-johanness>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Of course, this only holds true when the config is read, i.e. when
> setup_rerere() was called in time. Which is the case when you call
> rerere() (as is done both from cmd_rerere() as well as cmd_commit()).
>
> Of course, I haven't tested it. Other than running the test script, that
> is.
>
> So care to elaborate what is going wrong?
Very interesting question indeed.
^ permalink raw reply
* Breakage caused by 2fe403e7 git-svn.perl: workaround assertions in svn library 1.5.0
From: Kevin Ballard @ 2008-07-09 0:41 UTC (permalink / raw)
To: Git Mailing List, pape
Commit 2fe403e7 causes `git svn info` and `git svn info .` to break.
Use of uninitialized value in localtime at /usr/local/libexec/git-
core/git-svn line 4277.
No such file or directory at /usr/local/libexec/git-core/git-svn
line 897.
If it makes a difference, I have svn 1.4.4 installed, not svn 1.5.
-Kevin Ballard
--
Kevin Ballard
http://kevin.sb.org
kevin@sb.org
http://www.tildesoft.com
^ permalink raw reply
* Re: Merging a foreign tree into a bare repository.
From: Johannes Schindelin @ 2008-07-09 0:40 UTC (permalink / raw)
To: Dave Quigley; +Cc: Git Mailing List
In-Reply-To: <1215562468.4199.26.camel@moss-terrapins.epoch.ncsc.mil>
Hi,
On Tue, 8 Jul 2008, Dave Quigley wrote:
> I tried to then merge them but you need a working directory to merge the
> changes which makes sense.
Of course it does. Merging runs the risk of conflicts, and you need a
working directory for that.
> How would one go about doing this with a bare repository?
Very easy: clone it ("non-barely"), merge, and push back the results.
You _need_ a working directory for the merge.
Hth,
Dscho "who wonders what No Such Agency does with Git..."
^ permalink raw reply
* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
From: Johannes Schindelin @ 2008-07-09 0:38 UTC (permalink / raw)
To: Stephan Beyer; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.DEB.1.00.0807090225050.5277@eeepc-johanness>
Hi,
On Wed, 9 Jul 2008, Johannes Schindelin wrote:
> On Wed, 9 Jul 2008, Stephan Beyer wrote:
>
> > If a user reads the rerere documentation, he or she is not told to
> > create the $GIT_DIR/rr-cache directory to be able to use git-rerere.
>
> Is it? The config setting is not enough? Then that is a bug, and should
> not be blessed by a bug in the documentation.
Okay, I took a look:
-- snip --
static int is_rerere_enabled(void)
{
struct stat st;
const char *rr_cache;
int rr_cache_exists;
if (!rerere_enabled)
return 0;
rr_cache = git_path("rr-cache");
rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
if (rerere_enabled < 0)
return rr_cache_exists;
if (!rr_cache_exists &&
(mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
die("Could not create directory %s", rr_cache);
return 1;
}
-- snap --
As you can see, in the case rerere_enabled < 0 (i.e. the config did not
say anything about rerere), it is assumed enabled _exactly_ when
.git/rr_cache/ exists.
But if it is > 0, the directory is created.
Of course, this only holds true when the config is read, i.e. when
setup_rerere() was called in time. Which is the case when you call
rerere() (as is done both from cmd_rerere() as well as cmd_commit()).
Of course, I haven't tested it. Other than running the test script, that
is.
So care to elaborate what is going wrong?
BTW I think it is a horrible thing that rerere() is declared in commit.h
(a libgit header), but implemented in builtin-rerere.c, which is not part
of libgit.a.
Ciao,
Dscho
^ permalink raw reply
* Merging a foreign tree into a bare repository.
From: Dave Quigley @ 2008-07-09 0:14 UTC (permalink / raw)
To: Git Mailing List
Hello,
I created a bare copy of Linus' 2.6 kernel tree which I am using for
some public development. I have a branch in this tree called patchset
which has a series of commits based on a patch set that I have. Now I
want to update this copy from the kernel.org git repository and rebase
the patches in the patchset branch. I typed git-fetch <URL to Linus'
tree> and it successfully fetched the remote objects. I tried to then
merge them but you need a working directory to merge the changes which
makes sense. Normally if I had a working directory I would use
git-rebase to rebase my patches on a working tree but since this is a
bare repository I can't do that. How would one go about doing this with
a bare repository? Is there a better way of doing this that I am not
aware of? Is my work flow completely off?
Dave
^ permalink raw reply
* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
From: Johannes Schindelin @ 2008-07-09 0:25 UTC (permalink / raw)
To: Stephan Beyer; +Cc: Junio C Hamano, git
In-Reply-To: <1215562653-5043-1-git-send-email-s-beyer@gmx.net>
Hi,
On Wed, 9 Jul 2008, Stephan Beyer wrote:
> If a user reads the rerere documentation, he or she is not told to
> create the $GIT_DIR/rr-cache directory to be able to use git-rerere.
Is it? The config setting is not enough? Then that is a bug, and should
not be blessed by a bug in the documentation.
Ciao,
Dscho
^ permalink raw reply
* [PATCH] git-rerere.txt: Mention rr-cache directory
From: Stephan Beyer @ 2008-07-09 0:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Stephan Beyer
If a user reads the rerere documentation, he or she is not told to
create the $GIT_DIR/rr-cache directory to be able to use git-rerere.
This patch adds such a remark.
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
Documentation/git-rerere.txt | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index 678bfd3..667505c 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -23,8 +23,8 @@ initial manual merge, and later by noticing the same automerge
results and applying the previously recorded hand resolution.
[NOTE]
-You need to set the configuration variable rerere.enabled to
-enable this command.
+You need to set the configuration variable `rerere.enabled` and create
+the `rr-cache` directory under `$GIT_DIR` to enable this command.
COMMANDS
@@ -170,8 +170,8 @@ As a convenience measure, 'git-merge' automatically invokes
records it if it is a new conflict, or reuses the earlier hand
resolve when it is not. 'git-commit' also invokes 'git-rerere'
when recording a merge result. What this means is that you do
-not have to do anything special yourself (Note: you still have
-to set the config variable rerere.enabled to enable this command).
+not have to do anything special yourself, except making sure
+that `rerere.enabled` is set and `$GIT_DIR/rr-cache` exists.
In our example, when you did the test merge, the manual
resolution is recorded, and it will be reused when you do the
--
1.5.6.2.574.gd4568
^ permalink raw reply related
* Re: [PATCH] git-submodule - register module url if adding in place
From: Johannes Schindelin @ 2008-07-09 0:11 UTC (permalink / raw)
To: Mark Levedahl; +Cc: git
In-Reply-To: <4873FF6E.2020602@gmail.com>
Hi,
On Tue, 8 Jul 2008, Mark Levedahl wrote:
> Johannes Schindelin wrote:
> > I agree with Sylvain here, namely that this is too dangerous.
> > Imagine this very valid scenario:
> >
> > $ git clone <somewhere> abc
> > $ git submodule add abc
> >
> > Bummer.
> >
> > Yes, happened to me.
> >
> > So I'd like this to be an error, not something that tries to be
> > helpful, when it clearly cannot be.
>
> I think the real issue here is that submodule-add is too flexible and
> poorly documented, see my response to Junio in the other thread.
In contrast, I think that we should either disallow the form without URL,
or get the URL automatically from the submodule's current branch's default
remote.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] bash: offer only paths after '--'
From: Junio C Hamano @ 2008-07-09 0:06 UTC (permalink / raw)
To: SZEDER Gábor
Cc: Shawn O. Pearce, Johannes Schindelin, Eric Raible,
Git Mailing List
In-Reply-To: <20080708235153.GD8224@neumann>
SZEDER Gábor <szeder@ira.uka.de> writes:
> On Tue, Jul 08, 2008 at 11:18:37PM +0000, Shawn O. Pearce wrote:
>> Junio C Hamano <gitster@pobox.com> wrote:
>> > SZEDER Gábor <szeder@ira.uka.de> writes:
>> > > + c=$((++c))
>> >
>> > This assignment is somewhat curious, although it should work as expected
>> > either way ;-)
> ...
> Maybe an old C++ "heritage"? In C++ it matters for class types (e.g.
> iterators), because the postfix operator might be slower than the
> prefix.
Heh, I was not talking about prefix vs postfix but about the assignment
into the variable that is incremented as a side effect of evaluating the
left hand side. If you know the variable is incremented already there is
no point in assigning the resulting value to it ;-)
c=$(( $c + 1 ))
would have avoided such an uneasy feeling, and would have been more
portable. Even though $((x)) and $(($x)) are supposed to evaluate the
same, some shells do not like dollar-less variable names in arithmetic
expansion, and prefix/postfix increment/decrement are not required to be
supported by POSIX.
But this script being bash completion, we can use as much bashism as we
want here; perhaps I would have written:
: $((c++))
^ permalink raw reply
* Re: [PATCH] git-submodule - register module url if adding in place
From: Mark Levedahl @ 2008-07-08 23:59 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0807081332580.4319@eeepc-johanness>
Johannes Schindelin wrote:
> I agree with Sylvain here, namely that this is too dangerous. Imagine
> this very valid scenario:
>
> $ git clone <somewhere> abc
> $ git submodule add abc
>
> Bummer.
>
> Yes, happened to me.
>
> So I'd like this to be an error, not something that tries to be helpful,
> when it clearly cannot be.
>
> Ciao,
> Dscho
>
>
I think the real issue here is that submodule-add is too flexible and
poorly documented, see my response to Junio in the other thread.
Mark
^ permalink raw reply
* Re: [PATCH] fix "git-submodule add a/b/c/repository"
From: Mark Levedahl @ 2008-07-08 23:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Sylvain Joyeux, Lars Hjemli, Ping Yin, git
In-Reply-To: <7vhcb0x6ak.fsf@gitster.siamese.dyndns.org>
Junio C Hamano wrote:
> Thanks.
>
> The above is quite a bit more information than I can read from
> Documentation/git-submodule.txt; care to send it in in a patch form?
>
>
Will do, but I think it makes more sense to clean things up a bit so
they are more explicable:
1) *require* two arguments for add: <URL> <relative-path-in-repo>
2) Remove one option for URL. Currently, we accept:
a) absolute URL : origin is at URL
b) top-level-relative URL (./foo | ../foo) : locates origin relative
to top-level origin
c) path-relative URL : locates origin relative to current working
directory
I don't understand the use-case for item (c), and in any case it is
easily replaced as an abolute url (e.g., $(pwd)/URL). So, I propose to
restrict to (a) or (b) only, and reject (c).
I think these two changes in concert will reduce a lot of confusion
without removing any real capability. Absent negative comments, I will
prepare a patch to do this, *and* update the documentation to better
define the options.
Mark
^ permalink raw reply
* Re: [PATCH] bash: offer only paths after '--'
From: Shawn O. Pearce @ 2008-07-08 23:55 UTC (permalink / raw)
To: SZEDER GGGbor
Cc: Junio C Hamano, Johannes Schindelin, Eric Raible,
Git Mailing List
In-Reply-To: <20080708235153.GD8224@neumann>
SZEDER GGGbor <szeder@ira.uka.de> wrote:
> On Tue, Jul 08, 2008 at 11:18:37PM +0000, Shawn O. Pearce wrote:
> > Junio C Hamano <gitster@pobox.com> wrote:
> > > SZEDER Gábor <szeder@ira.uka.de> writes:
> > > > + c=$((++c))
> > >
> > > This assignment is somewhat curious, although it should work as expected
> > > either way ;-)
>
> Well, according to
>
> git blame contrib/completion/git-completion.bash |grep '++'
>
> you started this convention back in 2006, I just copied and modified
> your code (;
Yea, I don't doubt it was me that did this.
> Maybe an old C++ "heritage"? In C++ it matters for class types (e.g.
> iterators), because the postfix operator might be slower than the
> prefix.
Unlikely, but maybe. I'm not really a C++ programmer. I tend to
avoid C++ when/if I am given the chance to do so.
--
Shawn.
^ 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