diff options
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 37 |
1 files changed, 29 insertions, 8 deletions
@@ -390,6 +390,18 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re return retval; } +/* + * If the "reading" argument is set, this function finds out what _object_ + * the ref points at by "reading" the ref. The ref, if it is not symbolic, + * has to exist, and if it is symbolic, it has to point at an existing ref, + * because the "read" goes through the symref to the ref it points at. + * + * The access that is not "reading" may often be "writing", but does not + * have to; it can be merely checking _where it leads to_. If it is a + * prelude to "writing" to the ref, a write to a symref that points at + * yet-to-be-born ref will create the real ref pointed by the symref. + * reading=0 allows the caller to check where such a symref leads to. + */ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag) { int depth = MAXDEPTH; @@ -410,13 +422,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int * return NULL; git_snpath(path, sizeof(path), "%s", ref); - /* Special case: non-existing file. - * Not having the refs/heads/new-branch is OK - * if we are writing into it, so is .git/HEAD - * that points at refs/heads/master still to be - * born. It is NOT OK if we are resolving for - * reading. - */ + /* Special case: non-existing file. */ if (lstat(path, &st) < 0) { struct ref_list *list = get_packed_refs(); while (list) { @@ -1447,7 +1453,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * return 1; } -int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data) +int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, void *cb_data) { const char *logfile; FILE *logfp; @@ -1458,6 +1464,16 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data) logfp = fopen(logfile, "r"); if (!logfp) return -1; + + if (ofs) { + struct stat statbuf; + if (fstat(fileno(logfp), &statbuf) || + statbuf.st_size < ofs || + fseek(logfp, -ofs, SEEK_END) || + fgets(buf, sizeof(buf), logfp)) + return -1; + } + while (fgets(buf, sizeof(buf), logfp)) { unsigned char osha1[20], nsha1[20]; char *email_end, *message; @@ -1491,6 +1507,11 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data) return ret; } +int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data) +{ + return for_each_recent_reflog_ent(ref, fn, 0, cb_data); +} + static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data) { DIR *dir = opendir(git_path("logs/%s", base)); |