aboutsummaryrefslogtreecommitdiff
path: root/send-pack.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@evo.osdl.org>2005-07-19 07:03:47 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-07-19 07:03:47 -0400
commit2a9c3fe838a21cb2097347e15bec71e848f8d625 (patch)
treefc21098f5710a2333c4ad04d3571eb7580223bf9 /send-pack.c
parent07ee0d77c66d6f356cd3f82435e67510779aa53c (diff)
downloadgit-2a9c3fe838a21cb2097347e15bec71e848f8d625.tar.gz
git-2a9c3fe838a21cb2097347e15bec71e848f8d625.tar.xz
git-send-pack: verify that sender is a proper superset of receiver
This should make sure that if you have multiple people pushing to the same tree, they cannot overwrite each others work, but have to merge before being able to update the common reference tree.
Diffstat (limited to 'send-pack.c')
-rw-r--r--send-pack.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/send-pack.c b/send-pack.c
index 2994df401..2a7ab2d2b 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "commit.h"
#include "refs.h"
#include "pkt-line.h"
@@ -6,6 +7,7 @@ static const char send_pack_usage[] =
"git-send-pack [--exec=git-receive-pack] [host:]directory [heads]*";
static const char *exec = "git-receive-pack";
static int send_all = 0;
+static int force_update = 0;
static int is_zero_sha1(const unsigned char *sha1)
{
@@ -117,16 +119,26 @@ static int read_ref(const char *ref, unsigned char *sha1)
static int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1)
{
- if (!has_sha1_file(old_sha1))
+ struct commit *new, *old;
+ struct commit_list *list;
+
+ if (force_update)
+ return 1;
+ old = lookup_commit_reference(old_sha1);
+ if (!old)
return 0;
- /*
- * FIXME! It is not correct to say that the new one is newer
- * just because we don't have the old one!
- *
- * We should really see if we can reach the old_sha1 commit
- * from the new_sha1 one.
- */
- return 1;
+ new = lookup_commit_reference(new_sha1);
+ if (!new)
+ return 0;
+ if (parse_commit(new) < 0)
+ return 0;
+ list = NULL;
+ commit_list_insert(new, &list);
+ while ((new = pop_most_recent_commit(&list, 1)) != NULL) {
+ if (new == old)
+ return 1;
+ }
+ return 0;
}
static int local_ref_nr_match;
@@ -190,7 +202,7 @@ static int send_pack(int in, int out, int nr_match, char **match)
}
if (!ref_newer(new_sha1, ref->old_sha1)) {
- error("remote '%s' points to object I don't have", name);
+ error("remote '%s' isn't a strict parent of local", name);
continue;
}
@@ -252,6 +264,10 @@ int main(int argc, char **argv)
send_all = 1;
continue;
}
+ if (!strcmp(arg, "--force")) {
+ force_update = 1;
+ continue;
+ }
usage(send_pack_usage);
}
if (!dest) {