#include "cache.h"
+#include "commit.h"
#include "refs.h"
#include "pkt-line.h"
"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)
{
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;
}
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;
}
send_all = 1;
continue;
}
+ if (!strcmp(arg, "--force")) {
+ force_update = 1;
+ continue;
+ }
usage(send_pack_usage);
}
if (!dest) {