1 #define _XOPEN_SOURCE 500 /* glibc2 and AIX 5.3L need this */
2 #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
11 unsigned char old_sha1
[20];
12 unsigned char new_sha1
[20];
16 #define MAXOBJECTS (1000000)
18 static struct entry
*convert
[MAXOBJECTS
];
19 static int nr_convert
;
21 static struct entry
* convert_entry(unsigned char *sha1
);
23 static struct entry
*insert_new(unsigned char *sha1
, int pos
)
25 struct entry
*new = xcalloc(1, sizeof(struct entry
));
26 memcpy(new->old_sha1
, sha1
, 20);
27 memmove(convert
+ pos
+ 1, convert
+ pos
, (nr_convert
- pos
) * sizeof(struct entry
*));
30 if (nr_convert
== MAXOBJECTS
)
31 die("you're kidding me - hit maximum object limit");
35 static struct entry
*lookup_entry(unsigned char *sha1
)
37 int low
= 0, high
= nr_convert
;
40 int next
= (low
+ high
) / 2;
41 struct entry
*n
= convert
[next
];
42 int cmp
= hashcmp(sha1
, n
->old_sha1
);
51 return insert_new(sha1
, low
);
54 static void convert_binary_sha1(void *buffer
)
56 struct entry
*entry
= convert_entry(buffer
);
57 memcpy(buffer
, entry
->new_sha1
, 20);
60 static void convert_ascii_sha1(void *buffer
)
62 unsigned char sha1
[20];
65 if (get_sha1_hex(buffer
, sha1
))
66 die("expected sha1, got '%s'", (char*) buffer
);
67 entry
= convert_entry(sha1
);
68 memcpy(buffer
, sha1_to_hex(entry
->new_sha1
), 40);
71 static unsigned int convert_mode(unsigned int mode
)
75 newmode
= mode
& S_IFMT
;
77 newmode
|= (mode
& 0100) ? 0755 : 0644;
81 static int write_subdirectory(void *buffer
, unsigned long size
, const char *base
, int baselen
, unsigned char *result_sha1
)
83 char *new = xmalloc(size
);
84 unsigned long newlen
= 0;
89 int len
= 21 + strlen(buffer
);
90 char *path
= strchr(buffer
, ' ');
93 char *slash
, *origpath
;
95 if (!path
|| sscanf(buffer
, "%o", &mode
) != 1)
96 die("bad tree conversion");
97 mode
= convert_mode(mode
);
99 if (memcmp(path
, base
, baselen
))
103 slash
= strchr(path
, '/');
105 newlen
+= sprintf(new + newlen
, "%o %s", mode
, path
);
106 new[newlen
++] = '\0';
107 memcpy(new + newlen
, (char *) buffer
+ len
- 20, 20);
112 buffer
= (char *) buffer
+ len
;
116 newlen
+= sprintf(new + newlen
, "%o %.*s", S_IFDIR
, (int)(slash
- path
), path
);
118 sha1
= (unsigned char *)(new + newlen
);
121 len
= write_subdirectory(buffer
, size
, origpath
, slash
-origpath
+1, sha1
);
125 buffer
= (char *) buffer
+ len
;
128 write_sha1_file(new, newlen
, tree_type
, result_sha1
);
133 static void convert_tree(void *buffer
, unsigned long size
, unsigned char *result_sha1
)
135 void *orig_buffer
= buffer
;
136 unsigned long orig_size
= size
;
139 int len
= 1+strlen(buffer
);
141 convert_binary_sha1((char *) buffer
+ len
);
145 die("corrupt tree object");
147 buffer
= (char *) buffer
+ len
;
150 write_subdirectory(orig_buffer
, orig_size
, "", 0, result_sha1
);
153 static unsigned long parse_oldstyle_date(const char *buf
)
158 const char *formats
[] = {
166 /* We only ever did two timezones in the bad old format .. */
167 const char *timezones
[] = {
168 "PDT", "PST", "CEST", NULL
170 const char **fmt
= formats
;
173 while (isspace(c
= *buf
))
175 while ((c
= *buf
++) != '\n')
179 memset(&tm
, 0, sizeof(tm
));
181 const char *next
= strptime(buf
, *fmt
, &tm
);
187 const char **p
= timezones
;
188 while (isspace(*buf
))
191 if (!memcmp(buf
, *p
, strlen(*p
))) {
199 } while (*buf
&& *fmt
);
200 printf("left: %s\n", buf
);
204 static int convert_date_line(char *dst
, void **buf
, unsigned long *sp
)
206 unsigned long size
= *sp
;
208 char *next
= strchr(line
, '\n');
209 char *date
= strchr(line
, '>');
213 die("missing or bad author/committer line %s", line
);
217 *sp
= size
- (next
- line
);
220 memcpy(dst
, line
, len
);
223 /* Is it already in new format? */
224 if (isdigit(*date
)) {
225 int datelen
= next
- date
;
226 memcpy(dst
, date
, datelen
);
227 return len
+ datelen
;
231 * Hacky hacky: one of the sparse old-style commits does not have
232 * any date at all, but we can fake it by using the committer date.
234 if (*date
== '\n' && strchr(next
, '>'))
235 date
= strchr(next
, '>')+2;
237 return len
+ sprintf(dst
, "%lu -0700\n", parse_oldstyle_date(date
));
240 static void convert_date(void *buffer
, unsigned long size
, unsigned char *result_sha1
)
242 char *new = xmalloc(size
+ 100);
243 unsigned long newlen
= 0;
245 /* "tree <sha1>\n" */
246 memcpy(new + newlen
, buffer
, 46);
248 buffer
= (char *) buffer
+ 46;
251 /* "parent <sha1>\n" */
252 while (!memcmp(buffer
, "parent ", 7)) {
253 memcpy(new + newlen
, buffer
, 48);
255 buffer
= (char *) buffer
+ 48;
259 /* "author xyz <xyz> date" */
260 newlen
+= convert_date_line(new + newlen
, &buffer
, &size
);
261 /* "committer xyz <xyz> date" */
262 newlen
+= convert_date_line(new + newlen
, &buffer
, &size
);
265 memcpy(new + newlen
, buffer
, size
);
268 write_sha1_file(new, newlen
, commit_type
, result_sha1
);
272 static void convert_commit(void *buffer
, unsigned long size
, unsigned char *result_sha1
)
274 void *orig_buffer
= buffer
;
275 unsigned long orig_size
= size
;
277 if (memcmp(buffer
, "tree ", 5))
278 die("Bad commit '%s'", (char*) buffer
);
279 convert_ascii_sha1((char *) buffer
+ 5);
280 buffer
= (char *) buffer
+ 46; /* "tree " + "hex sha1" + "\n" */
281 while (!memcmp(buffer
, "parent ", 7)) {
282 convert_ascii_sha1((char *) buffer
+ 7);
283 buffer
= (char *) buffer
+ 48;
285 convert_date(orig_buffer
, orig_size
, result_sha1
);
288 static struct entry
* convert_entry(unsigned char *sha1
)
290 struct entry
*entry
= lookup_entry(sha1
);
295 if (entry
->converted
)
297 data
= read_sha1_file(sha1
, type
, &size
);
299 die("unable to read object %s", sha1_to_hex(sha1
));
301 buffer
= xmalloc(size
);
302 memcpy(buffer
, data
, size
);
304 if (!strcmp(type
, blob_type
)) {
305 write_sha1_file(buffer
, size
, blob_type
, entry
->new_sha1
);
306 } else if (!strcmp(type
, tree_type
))
307 convert_tree(buffer
, size
, entry
->new_sha1
);
308 else if (!strcmp(type
, commit_type
))
309 convert_commit(buffer
, size
, entry
->new_sha1
);
311 die("unknown object type '%s' in %s", type
, sha1_to_hex(sha1
));
312 entry
->converted
= 1;
318 int main(int argc
, char **argv
)
320 unsigned char sha1
[20];
323 setup_git_directory();
326 usage("git-convert-objects <sha1>");
327 if (get_sha1(argv
[1], sha1
))
328 die("Not a valid object name %s", argv
[1]);
330 entry
= convert_entry(sha1
);
331 printf("new sha1: %s\n", sha1_to_hex(entry
->new_sha1
));