8 struct complete_reflogs
{
11 unsigned char osha1
[20], nsha1
[20];
13 unsigned long timestamp
;
20 static int read_one_reflog(unsigned char *osha1
, unsigned char *nsha1
,
21 const char *email
, unsigned long timestamp
, int tz
,
22 const char *message
, void *cb_data
)
24 struct complete_reflogs
*array
= cb_data
;
25 struct reflog_info
*item
;
27 if (array
->nr
>= array
->alloc
) {
28 array
->alloc
= alloc_nr(array
->nr
+ 1);
29 array
->items
= xrealloc(array
->items
, array
->alloc
*
30 sizeof(struct reflog_info
));
32 item
= array
->items
+ array
->nr
;
33 memcpy(item
->osha1
, osha1
, 20);
34 memcpy(item
->nsha1
, nsha1
, 20);
35 item
->email
= xstrdup(email
);
36 item
->timestamp
= timestamp
;
38 item
->message
= xstrdup(message
);
43 static struct complete_reflogs
*read_complete_reflog(const char *ref
)
45 struct complete_reflogs
*reflogs
=
46 xcalloc(sizeof(struct complete_reflogs
), 1);
47 reflogs
->ref
= xstrdup(ref
);
48 for_each_reflog_ent(ref
, read_one_reflog
, reflogs
);
49 if (reflogs
->nr
== 0) {
50 unsigned char sha1
[20];
51 const char *name
= resolve_ref(ref
, sha1
, 1, NULL
);
53 for_each_reflog_ent(name
, read_one_reflog
, reflogs
);
55 if (reflogs
->nr
== 0) {
56 int len
= strlen(ref
);
57 char *refname
= xmalloc(len
+ 12);
58 sprintf(refname
, "refs/%s", ref
);
59 for_each_reflog_ent(refname
, read_one_reflog
, reflogs
);
60 if (reflogs
->nr
== 0) {
61 sprintf(refname
, "refs/heads/%s", ref
);
62 for_each_reflog_ent(refname
, read_one_reflog
, reflogs
);
69 static int get_reflog_recno_by_time(struct complete_reflogs
*array
,
70 unsigned long timestamp
)
73 for (i
= array
->nr
- 1; i
>= 0; i
++)
74 if (timestamp
>= array
->items
[i
].timestamp
)
79 struct commit_info_lifo
{
81 struct commit
*commit
;
87 static struct commit_info
*get_commit_info(struct commit
*commit
,
88 struct commit_info_lifo
*lifo
, int pop
)
91 for (i
= 0; i
< lifo
->nr
; i
++)
92 if (lifo
->items
[i
].commit
== commit
) {
93 struct commit_info
*result
= &lifo
->items
[i
];
96 memmove(lifo
->items
+ i
,
99 sizeof(struct commit_info
));
107 static void add_commit_info(struct commit
*commit
, void *util
,
108 struct commit_info_lifo
*lifo
)
110 struct commit_info
*info
;
111 if (lifo
->nr
>= lifo
->alloc
) {
112 lifo
->alloc
= alloc_nr(lifo
->nr
+ 1);
113 lifo
->items
= xrealloc(lifo
->items
,
114 lifo
->alloc
* sizeof(struct commit_info
));
116 info
= lifo
->items
+ lifo
->nr
;
117 info
->commit
= commit
;
122 struct commit_reflog
{
124 struct complete_reflogs
*reflogs
;
127 struct reflog_walk_info
{
128 struct commit_info_lifo reflogs
;
129 struct path_list complete_reflogs
;
130 struct commit_reflog
*last_commit_reflog
;
133 void init_reflog_walk(struct reflog_walk_info
** info
)
135 *info
= xcalloc(sizeof(struct reflog_walk_info
), 1);
138 void add_reflog_for_walk(struct reflog_walk_info
*info
,
139 struct commit
*commit
, const char *name
)
141 unsigned long timestamp
= 0;
143 struct path_list_item
*item
;
144 struct complete_reflogs
*reflogs
;
145 char *branch
, *at
= strchr(name
, '@');
146 struct commit_reflog
*commit_reflog
;
148 if (commit
->object
.flags
& UNINTERESTING
)
149 die ("Cannot walk reflogs for %s", name
);
151 branch
= xstrdup(name
);
152 if (at
&& at
[1] == '{') {
154 branch
[at
- name
] = '\0';
155 recno
= strtoul(at
+ 2, &ep
, 10);
158 timestamp
= approxidate(at
+ 2);
163 item
= path_list_lookup(branch
, &info
->complete_reflogs
);
165 reflogs
= item
->util
;
167 reflogs
= read_complete_reflog(branch
);
168 if (!reflogs
|| reflogs
->nr
== 0)
169 die("No reflogs found for '%s'", branch
);
170 path_list_insert(branch
, &info
->complete_reflogs
)->util
174 commit_reflog
= xcalloc(sizeof(struct commit_reflog
), 1);
176 commit_reflog
->flag
= 1;
177 commit_reflog
->recno
= get_reflog_recno_by_time(reflogs
, timestamp
);
178 if (commit_reflog
->recno
< 0) {
184 commit_reflog
->recno
= reflogs
->nr
- recno
- 1;
185 commit_reflog
->reflogs
= reflogs
;
187 add_commit_info(commit
, commit_reflog
, &info
->reflogs
);
190 void fake_reflog_parent(struct reflog_walk_info
*info
, struct commit
*commit
)
192 struct commit_info
*commit_info
=
193 get_commit_info(commit
, &info
->reflogs
, 0);
194 struct commit_reflog
*commit_reflog
;
195 struct reflog_info
*reflog
;
197 info
->last_commit_reflog
= NULL
;
201 commit_reflog
= commit_info
->util
;
202 if (commit_reflog
->recno
< 0) {
203 commit
->parents
= NULL
;
207 reflog
= &commit_reflog
->reflogs
->items
[commit_reflog
->recno
];
208 info
->last_commit_reflog
= commit_reflog
;
209 commit_reflog
->recno
--;
210 commit_info
->commit
= (struct commit
*)parse_object(reflog
->osha1
);
211 if (!commit_info
->commit
) {
212 commit
->parents
= NULL
;
216 commit
->parents
= xcalloc(sizeof(struct commit_list
), 1);
217 commit
->parents
->item
= commit_info
->commit
;
218 commit
->object
.flags
&= ~(ADDED
| SEEN
| SHOWN
);
221 void show_reflog_message(struct reflog_walk_info
* info
)
223 if (info
&& info
->last_commit_reflog
) {
224 struct commit_reflog
*commit_reflog
= info
->last_commit_reflog
;
225 struct reflog_info
*info
;
227 printf("Reflog: %s@{", commit_reflog
->reflogs
->ref
);
228 info
= &commit_reflog
->reflogs
->items
[commit_reflog
->recno
+ 1];
229 if (commit_reflog
->flag
)
230 printf("%s", show_rfc2822_date(info
->timestamp
,
233 printf("%d", commit_reflog
->reflogs
->nr
234 - 2 - commit_reflog
->recno
);
235 printf("} (%s)\nReflog message: %s",
236 info
->email
, info
->message
);