Skip to content

Commit

Permalink
prune: clean .git/shallow after pruning objects
Browse files Browse the repository at this point in the history
This patch teaches "prune" to remove shallow roots that are no longer
reachable from any refs (e.g. when the relevant refs are removed).

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Dec 11, 2013
1 parent 0d7d285 commit eab3296
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Documentation/git-prune.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ objects unreachable from any of these head objects from the object database.
In addition, it
prunes the unpacked objects that are also found in packs by
running 'git prune-packed'.
It also removes entries from .git/shallow that are not reachable by
any ref.

Note that unreachable, packed objects will remain. If this is
not desired, see linkgit:git-repack[1].
Expand Down
1 change: 1 addition & 0 deletions builtin/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "run-command.h"
#include "sigchain.h"
#include "argv-array.h"
#include "commit.h"

#define FAILED_RUN "failed to run %s"

Expand Down
4 changes: 4 additions & 0 deletions builtin/prune.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,9 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
s = mkpathdup("%s/pack", get_object_directory());
remove_temporary_files(s);
free(s);

if (is_repository_shallow())
prune_shallow(show_only);

return 0;
}
1 change: 1 addition & 0 deletions commit.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ extern void assign_shallow_commits_to_refs(struct shallow_info *info,
uint32_t **used,
int *ref_status);
extern int delayed_reachability_test(struct shallow_info *si, int c);
extern void prune_shallow(int show_only);

int is_descendant_of(struct commit *, struct commit_list *);
int in_merge_bases(struct commit *, struct commit *);
Expand Down
55 changes: 53 additions & 2 deletions shallow.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,14 @@ void check_shallow_file_for_update(void)
die("shallow file was changed during fetch");
}

#define SEEN_ONLY 1
#define VERBOSE 2

struct write_shallow_data {
struct strbuf *out;
int use_pack_protocol;
int count;
unsigned flags;
};

static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
Expand All @@ -167,6 +171,15 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
const char *hex = sha1_to_hex(graft->sha1);
if (graft->nr_parent != -1)
return 0;
if (data->flags & SEEN_ONLY) {
struct commit *c = lookup_commit(graft->sha1);
if (!c || !(c->object.flags & SEEN)) {
if (data->flags & VERBOSE)
printf("Removing %s from .git/shallow\n",
sha1_to_hex(c->object.sha1));
return 0;
}
}
data->count++;
if (data->use_pack_protocol)
packet_buf_write(data->out, "shallow %s", hex);
Expand All @@ -177,14 +190,16 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
return 0;
}

int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
const struct sha1_array *extra)
static int write_shallow_commits_1(struct strbuf *out, int use_pack_protocol,
const struct sha1_array *extra,
unsigned flags)
{
struct write_shallow_data data;
int i;
data.out = out;
data.use_pack_protocol = use_pack_protocol;
data.count = 0;
data.flags = flags;
for_each_commit_graft(write_one_shallow, &data);
if (!extra)
return data.count;
Expand All @@ -196,6 +211,12 @@ int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
return data.count;
}

int write_shallow_commits(struct strbuf *out, int use_pack_protocol,
const struct sha1_array *extra)
{
return write_shallow_commits_1(out, use_pack_protocol, extra, 0);
}

char *setup_temporary_shallow(const struct sha1_array *extra)
{
struct strbuf sb = STRBUF_INIT;
Expand Down Expand Up @@ -258,6 +279,36 @@ void advertise_shallow_grafts(int fd)
for_each_commit_graft(advertise_shallow_grafts_cb, &fd);
}

/*
* mark_reachable_objects() should have been run prior to this and all
* reachable commits marked as "SEEN".
*/
void prune_shallow(int show_only)
{
static struct lock_file shallow_lock;
struct strbuf sb = STRBUF_INIT;
int fd;

if (show_only) {
write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY | VERBOSE);
strbuf_release(&sb);
return;
}
check_shallow_file_for_update();
fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"),
LOCK_DIE_ON_ERROR);
if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
if (write_in_full(fd, sb.buf, sb.len) != sb.len)
die_errno("failed to write to %s",
shallow_lock.filename);
commit_lock_file(&shallow_lock);
} else {
unlink(git_path("shallow"));
rollback_lock_file(&shallow_lock);
}
strbuf_release(&sb);
}

#define TRACE_KEY "GIT_TRACE_SHALLOW"

/*
Expand Down
10 changes: 10 additions & 0 deletions t/t5304-prune.sh
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,14 @@ EOF
test_cmp expected actual
'

test_expect_success 'prune .git/shallow' '
SHA1=`echo hi|git commit-tree HEAD^{tree}` &&
echo $SHA1 >.git/shallow &&
git prune --dry-run >out &&
grep $SHA1 .git/shallow &&
grep $SHA1 out &&
git prune &&
! test -f .git/shallow
'

test_done

0 comments on commit eab3296

Please sign in to comment.