allow deepening of a shallow repository
Now, by saying "git fetch -depth <n> <repo>" you can deepen a shallow repository. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:

committed by
Junio C Hamano

parent
016e6ccbe0
commit
f53514bc2d
13
commit.c
13
commit.c
@ -255,6 +255,19 @@ int write_shallow_commits(int fd, int use_pack_protocol)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int unregister_shallow(const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
int pos = commit_graft_pos(sha1);
|
||||||
|
if (pos < 0)
|
||||||
|
return -1;
|
||||||
|
if (pos + 1 < commit_graft_nr)
|
||||||
|
memcpy(commit_graft + pos, commit_graft + pos + 1,
|
||||||
|
sizeof(struct commit_graft *)
|
||||||
|
* (commit_graft_nr - pos - 1));
|
||||||
|
commit_graft_nr--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
||||||
{
|
{
|
||||||
char *tail = buffer;
|
char *tail = buffer;
|
||||||
|
3
commit.h
3
commit.h
@ -108,9 +108,10 @@ int read_graft_file(const char *graft_file);
|
|||||||
extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
|
extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
|
||||||
|
|
||||||
extern int register_shallow(const unsigned char *sha1);
|
extern int register_shallow(const unsigned char *sha1);
|
||||||
|
extern int unregister_shallow(const unsigned char *sha1);
|
||||||
extern int write_shallow_commits(int fd, int use_pack_protocol);
|
extern int write_shallow_commits(int fd, int use_pack_protocol);
|
||||||
extern int is_repository_shallow();
|
extern int is_repository_shallow();
|
||||||
extern struct commit_list *get_shallow_commits(struct object_array *heads,
|
extern struct commit_list *get_shallow_commits(struct object_array *heads,
|
||||||
int depth);
|
int depth, int shallow_flag, int not_shallow_flag);
|
||||||
|
|
||||||
#endif /* COMMIT_H */
|
#endif /* COMMIT_H */
|
||||||
|
22
fetch-pack.c
22
fetch-pack.c
@ -202,7 +202,17 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
|||||||
if (lookup_object(sha1))
|
if (lookup_object(sha1))
|
||||||
continue;
|
continue;
|
||||||
register_shallow(sha1);
|
register_shallow(sha1);
|
||||||
}
|
} else if (!strncmp("unshallow ", line, 10)) {
|
||||||
|
if (get_sha1_hex(line + 10, sha1))
|
||||||
|
die("invalid unshallow line: %s", line);
|
||||||
|
if (!lookup_object(sha1))
|
||||||
|
die("object not found: %s", line);
|
||||||
|
/* make sure that it is parsed as shallow */
|
||||||
|
parse_object(sha1);
|
||||||
|
if (unregister_shallow(sha1))
|
||||||
|
die("no shallow found: %s", line);
|
||||||
|
} else
|
||||||
|
die("expected shallow/unshallow, got %s", line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,9 +401,11 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_ref(mark_complete, NULL);
|
if (!depth) {
|
||||||
if (cutoff)
|
for_each_ref(mark_complete, NULL);
|
||||||
mark_recent_complete_commits(cutoff);
|
if (cutoff)
|
||||||
|
mark_recent_complete_commits(cutoff);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark all complete remote refs as common refs.
|
* Mark all complete remote refs as common refs.
|
||||||
@ -646,8 +658,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!dest)
|
if (!dest)
|
||||||
usage(fetch_pack_usage);
|
usage(fetch_pack_usage);
|
||||||
if (is_repository_shallow() && depth > 0)
|
|
||||||
die("Deepening of a shallow repository not yet supported!");
|
|
||||||
pid = git_connect(fd, dest, exec);
|
pid = git_connect(fd, dest, exec);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
14
git-fetch.sh
14
git-fetch.sh
@ -21,6 +21,7 @@ update_head_ok=
|
|||||||
exec=
|
exec=
|
||||||
upload_pack=
|
upload_pack=
|
||||||
keep=
|
keep=
|
||||||
|
shallow_depth=
|
||||||
while case "$#" in 0) break ;; esac
|
while case "$#" in 0) break ;; esac
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@ -56,6 +57,13 @@ do
|
|||||||
--reflog-action=*)
|
--reflog-action=*)
|
||||||
rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
|
rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
|
||||||
;;
|
;;
|
||||||
|
--depth=*)
|
||||||
|
shallow_depth="--depth=`expr "z$1" : 'z-[^=]*=\(.*\)'`"
|
||||||
|
;;
|
||||||
|
--depth)
|
||||||
|
shift
|
||||||
|
shallow_depth="--depth=$1"
|
||||||
|
;;
|
||||||
-*)
|
-*)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
@ -296,6 +304,8 @@ fetch_main () {
|
|||||||
# There are transports that can fetch only one head at a time...
|
# There are transports that can fetch only one head at a time...
|
||||||
case "$remote" in
|
case "$remote" in
|
||||||
http://* | https://* | ftp://*)
|
http://* | https://* | ftp://*)
|
||||||
|
test -n "$shallow_depth" &&
|
||||||
|
die "shallow clone with http not supported"
|
||||||
proto=`expr "$remote" : '\([^:]*\):'`
|
proto=`expr "$remote" : '\([^:]*\):'`
|
||||||
if [ -n "$GIT_SSL_NO_VERIFY" ]; then
|
if [ -n "$GIT_SSL_NO_VERIFY" ]; then
|
||||||
curl_extra_args="-k"
|
curl_extra_args="-k"
|
||||||
@ -324,6 +334,8 @@ fetch_main () {
|
|||||||
git-http-fetch -v -a "$head" "$remote/" || exit
|
git-http-fetch -v -a "$head" "$remote/" || exit
|
||||||
;;
|
;;
|
||||||
rsync://*)
|
rsync://*)
|
||||||
|
test -n "$shallow_depth" &&
|
||||||
|
die "shallow clone with rsync not supported"
|
||||||
TMP_HEAD="$GIT_DIR/TMP_HEAD"
|
TMP_HEAD="$GIT_DIR/TMP_HEAD"
|
||||||
rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
|
rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
|
||||||
head=$(git-rev-parse --verify TMP_HEAD)
|
head=$(git-rev-parse --verify TMP_HEAD)
|
||||||
@ -371,7 +383,7 @@ fetch_main () {
|
|||||||
pack_lockfile=
|
pack_lockfile=
|
||||||
IFS=" $LF"
|
IFS=" $LF"
|
||||||
(
|
(
|
||||||
git-fetch-pack --thin $exec $keep "$remote" $rref || echo failed "$remote"
|
git-fetch-pack --thin $exec $keep $shallow_depth "$remote" $rref || echo failed "$remote"
|
||||||
) |
|
) |
|
||||||
while read sha1 remote_name
|
while read sha1 remote_name
|
||||||
do
|
do
|
||||||
|
@ -41,7 +41,8 @@ int is_repository_shallow()
|
|||||||
return is_shallow;
|
return is_shallow;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct commit_list *get_shallow_commits(struct object_array *heads, int depth)
|
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
||||||
|
int shallow_flag, int not_shallow_flag)
|
||||||
{
|
{
|
||||||
int i = 0, cur_depth = 0;
|
int i = 0, cur_depth = 0;
|
||||||
struct commit_list *result = NULL;
|
struct commit_list *result = NULL;
|
||||||
@ -67,6 +68,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
parse_commit(commit);
|
parse_commit(commit);
|
||||||
|
commit->object.flags |= not_shallow_flag;
|
||||||
cur_depth++;
|
cur_depth++;
|
||||||
for (p = commit->parents, commit = NULL; p; p = p->next) {
|
for (p = commit->parents, commit = NULL; p; p = p->next) {
|
||||||
if (!p->item->util) {
|
if (!p->item->util) {
|
||||||
@ -87,8 +89,10 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth)
|
|||||||
commit = p->item;
|
commit = p->item;
|
||||||
cur_depth = *(int *)commit->util;
|
cur_depth = *(int *)commit->util;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
commit_list_insert(p->item, &result);
|
commit_list_insert(p->item, &result);
|
||||||
|
p->item->object.flags |= shallow_flag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=n
|
|||||||
#define COMMON_KNOWN (1u << 14)
|
#define COMMON_KNOWN (1u << 14)
|
||||||
#define REACHABLE (1u << 15)
|
#define REACHABLE (1u << 15)
|
||||||
|
|
||||||
|
#define SHALLOW (1u << 16)
|
||||||
|
#define NOT_SHALLOW (1u << 17)
|
||||||
|
#define CLIENT_SHALLOW (1u << 18)
|
||||||
|
|
||||||
static unsigned long oldest_have;
|
static unsigned long oldest_have;
|
||||||
|
|
||||||
static int multi_ack, nr_our_refs;
|
static int multi_ack, nr_our_refs;
|
||||||
@ -134,6 +138,7 @@ static void create_pack_file(void)
|
|||||||
} else {
|
} else {
|
||||||
for (i = 0; i < want_obj.nr; i++) {
|
for (i = 0; i < want_obj.nr; i++) {
|
||||||
struct object *o = want_obj.objects[i].item;
|
struct object *o = want_obj.objects[i].item;
|
||||||
|
o->flags &= ~UNINTERESTING;
|
||||||
add_pending_object(&revs, o, NULL);
|
add_pending_object(&revs, o, NULL);
|
||||||
}
|
}
|
||||||
for (i = 0; i < have_obj.nr; i++) {
|
for (i = 0; i < have_obj.nr; i++) {
|
||||||
@ -501,16 +506,19 @@ static void receive_needs(void)
|
|||||||
if (!strncmp("shallow ", line, 8)) {
|
if (!strncmp("shallow ", line, 8)) {
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
struct object *object;
|
struct object *object;
|
||||||
|
use_thin_pack = 0;
|
||||||
if (get_sha1(line + 8, sha1))
|
if (get_sha1(line + 8, sha1))
|
||||||
die("invalid shallow line: %s", line);
|
die("invalid shallow line: %s", line);
|
||||||
object = parse_object(sha1);
|
object = parse_object(sha1);
|
||||||
if (!object)
|
if (!object)
|
||||||
die("did not find object for %s", line);
|
die("did not find object for %s", line);
|
||||||
|
object->flags |= CLIENT_SHALLOW;
|
||||||
add_object_array(object, NULL, &shallows);
|
add_object_array(object, NULL, &shallows);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strncmp("deepen ", line, 7)) {
|
if (!strncmp("deepen ", line, 7)) {
|
||||||
char *end;
|
char *end;
|
||||||
|
use_thin_pack = 0;
|
||||||
depth = strtol(line + 7, &end, 0);
|
depth = strtol(line + 7, &end, 0);
|
||||||
if (end == line + 7 || depth <= 0)
|
if (end == line + 7 || depth <= 0)
|
||||||
die("Invalid deepen: %s", line);
|
die("Invalid deepen: %s", line);
|
||||||
@ -547,23 +555,51 @@ static void receive_needs(void)
|
|||||||
add_object_array(o, NULL, &want_obj);
|
add_object_array(o, NULL, &want_obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (depth == 0 && shallows.nr == 0)
|
||||||
|
return;
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
struct commit_list *result, *backup;
|
struct commit_list *result, *backup;
|
||||||
if (shallows.nr > 0)
|
int i;
|
||||||
die("Deepening a shallow repository not yet supported");
|
backup = result = get_shallow_commits(&want_obj, depth,
|
||||||
backup = result = get_shallow_commits(&want_obj, depth);
|
SHALLOW, NOT_SHALLOW);
|
||||||
while (result) {
|
while (result) {
|
||||||
packet_write(1, "shallow %s",
|
struct object *object = &result->item->object;
|
||||||
sha1_to_hex(result->item->object.sha1));
|
if (!(object->flags & CLIENT_SHALLOW)) {
|
||||||
|
packet_write(1, "shallow %s",
|
||||||
|
sha1_to_hex(object->sha1));
|
||||||
|
register_shallow(object->sha1);
|
||||||
|
}
|
||||||
result = result->next;
|
result = result->next;
|
||||||
}
|
}
|
||||||
free_commit_list(backup);
|
free_commit_list(backup);
|
||||||
}
|
for (i = 0; i < shallows.nr; i++) {
|
||||||
if (shallows.nr > 0) {
|
struct object *object = shallows.objects[i].item;
|
||||||
int i;
|
if (object->flags & NOT_SHALLOW) {
|
||||||
for (i = 0; i < shallows.nr; i++)
|
struct commit_list *parents;
|
||||||
register_shallow(shallows.objects[i].item->sha1);
|
packet_write(1, "unshallow %s",
|
||||||
}
|
sha1_to_hex(object->sha1));
|
||||||
|
object->flags &= ~CLIENT_SHALLOW;
|
||||||
|
/* make sure the real parents are parsed */
|
||||||
|
unregister_shallow(object->sha1);
|
||||||
|
parse_commit((struct commit *)object);
|
||||||
|
parents = ((struct commit *)object)->parents;
|
||||||
|
while (parents) {
|
||||||
|
add_object_array(&parents->item->object,
|
||||||
|
NULL, &want_obj);
|
||||||
|
parents = parents->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* make sure commit traversal conforms to client */
|
||||||
|
register_shallow(object->sha1);
|
||||||
|
}
|
||||||
|
packet_flush(1);
|
||||||
|
} else
|
||||||
|
if (shallows.nr > 0) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < shallows.nr; i++)
|
||||||
|
register_shallow(shallows.objects[i].item->sha1);
|
||||||
|
}
|
||||||
|
free(shallows.objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
|
static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
|
||||||
|
Reference in New Issue
Block a user