Public » Mercurial » dirstate
Clone URL:  
Pushed to one repository · View In Graph Contained in tip

initial dirstate reader

Changeset 3f2845a0be6a

Parent c328000d1793

by Profile picture of Benjamin PollackBenjamin Pollack

Changes to one file · Browse files at 3f2845a0be6a Showing diff from parent c328000d1793 Diff from another changeset...

Change 1 of 1 Show Entire File dirstate.c Stacked
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@@ -0,0 +1,96 @@
+#include <stdio.h> +#include <stdlib.h> +#include <strings.h> + +#define HASH_LENGTH 20 + +typedef struct _direntry +{ + /* <1-byte state><4-byte mode><4-byte size><4-byte mtime><4-byte name length><n-byte name> */ + unsigned char state; + unsigned mode; + unsigned size; + unsigned mtime; + unsigned length; + char *name; + char *origname; +} direntry; + +typedef struct _dirstate +{ + char parent1[HASH_LENGTH]; + char parent2[HASH_LENGTH]; + + unsigned num_entries; + direntry *entries; + unsigned __entries_length; +} dirstate; + +void dirstate_add_entry(dirstate *d, const direntry *e) +{ + if (d->num_entries == d->__entries_length) + { + d->__entries_length = d->__entries_length ? 2 * d->__entries_length : 1; + d->entries = realloc(d->entries, d->__entries_length * sizeof(direntry)); + } + d->entries[d->num_entries++] = *e; +} + +dirstate *dirstate_new(const char *path) +{ + direntry e; + FILE *f = fopen(path, "r"); + if (!f) return NULL; + dirstate *d = calloc(1, sizeof(dirstate)); + fread(&d->parent1, sizeof(char), HASH_LENGTH, f); + fread(&d->parent2, sizeof(char), HASH_LENGTH, f); + + while (fread(&e.state, sizeof(e.state), 1, f) == 1) + { + fread(&e.mode, sizeof(e.mode), 1, f); + fread(&e.size, sizeof(e.size), 1, f); + fread(&e.mtime, sizeof(e.mtime), 1, f); + fread(&e.length, sizeof(e.length), 1, f); + e.name = malloc(e.length * sizeof(char) + 1); + fread(e.name, sizeof(char), e.length, f); + e.name[e.length] = 0; + dirstate_add_entry(d, &e); + } + + return d; +} + +void dirstate_free(dirstate *d) +{ + unsigned ix; + for (ix = 0; ix < d->num_entries; ++ix) free(d->entries[ix].name); + free(d); +} + +static char *rev_string(const char revhash[HASH_LENGTH]) +{ + unsigned ix; + static char rev_string[HASH_LENGTH * 2]; + static char *hexval = "0123456789abcdef"; + for (ix = 0; ix < HASH_LENGTH; ++ix) + { + rev_string[ix * 2] = hexval[(revhash[ix] >> 4) & 0xf]; + rev_string[ix * 2 + 1] = hexval[revhash[ix] & 0xf]; + } + return rev_string; +} + +int main(int argc, char *argv[]) +{ + dirstate *d = dirstate_new(".hg/dirstate"); + unsigned ix; + printf("parent1: %s\n", rev_string(d->parent1)); + printf("parent2: %s\n", rev_string(d->parent2)); + printf("entries: %d\n", d->num_entries); + for (ix = 0; ix < d->num_entries; ++ix) + { + printf("entry: %s\n", d->entries[ix].name); + } + dirstate_free(d); + return 0; +}