1#include "cache.h"
2#include "commit.h"
3#include "diff.h"
4#include "revision.h"
5#include "builtin.h"
6#include "reachable.h"
78
static const char prune_usage[] = "git-prune [-n]";
9static int show_only;
10static unsigned long expire;
1112
static int prune_object(char *path, const char *filename, const unsigned char *sha1)
13{
14const char *fullpath = mkpath("%s/%s", path, filename);
15if (expire) {
16struct stat st;
17if (lstat(fullpath, &st))
18return error("Could not stat '%s'", fullpath);
19if (st.st_mtime > expire)
20return 0;
21}
22if (show_only) {
23enum object_type type = sha1_object_info(sha1, NULL);
24printf("%s %s\n", sha1_to_hex(sha1),
25(type > 0) ? typename(type) : "unknown");
26} else
27unlink(fullpath);
28return 0;
29}
3031
static int prune_dir(int i, char *path)
32{
33DIR *dir = opendir(path);
34struct dirent *de;
3536
if (!dir)
37return 0;
3839
while ((de = readdir(dir)) != NULL) {
40char name[100];
41unsigned char sha1[20];
42int len = strlen(de->d_name);
4344
switch (len) {
45case 2:
46if (de->d_name[1] != '.')
47break;
48case 1:
49if (de->d_name[0] != '.')
50break;
51continue;
52case 38:
53sprintf(name, "%02x", i);
54memcpy(name+2, de->d_name, len+1);
55if (get_sha1_hex(name, sha1) < 0)
56break;
5758
/*
59* Do we know about this object?
60* It must have been reachable
61*/
62if (lookup_object(sha1))
63continue;
6465
prune_object(path, de->d_name, sha1);
66continue;
67}
68fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
69}
70if (!show_only)
71rmdir(path);
72closedir(dir);
73return 0;
74}
7576
static void prune_object_dir(const char *path)
77{
78int i;
79for (i = 0; i < 256; i++) {
80static char dir[4096];
81sprintf(dir, "%s/%02x", path, i);
82prune_dir(i, dir);
83}
84}
8586
int cmd_prune(int argc, const char **argv, const char *prefix)
87{
88int i;
89struct rev_info revs;
9091
for (i = 1; i < argc; i++) {
92const char *arg = argv[i];
93if (!strcmp(arg, "-n")) {
94show_only = 1;
95continue;
96}
97if (!strcmp(arg, "--expire")) {
98if (++i < argc) {
99expire = approxidate(argv[i]);
100continue;
101}
102}
103else if (!prefixcmp(arg, "--expire=")) {
104expire = approxidate(arg + 9);
105continue;
106}
107usage(prune_usage);
108}
109110
save_commit_buffer = 0;
111init_revisions(&revs, prefix);
112mark_reachable_objects(&revs, 1);
113114
prune_object_dir(get_object_directory());
115116
sync();
117prune_packed_objects(show_only);
118return 0;
119}