-rw-r--r-- | cgit.h | 5 | ||||
-rw-r--r-- | shared.c | 47 |
2 files changed, 50 insertions, 2 deletions
@@ -1,45 +1,46 @@ #ifndef CGIT_H #define CGIT_H #include <git-compat-util.h> #include <cache.h> #include <grep.h> #include <object.h> #include <tree.h> #include <commit.h> #include <tag.h> #include <diff.h> #include <diffcore.h> #include <refs.h> #include <revision.h> #include <log-tree.h> #include <archive.h> #include <xdiff/xdiff.h> typedef void (*configfn)(const char *name, const char *value); +typedef void (*filepair_fn)(struct diff_filepair *pair); struct cacheitem { char *name; struct stat st; int ttl; int fd; }; struct repoinfo { char *url; char *name; char *path; char *desc; char *owner; char *module_link; int snapshots; }; struct repolist { int length; int count; struct repoinfo *repos; }; @@ -95,48 +96,52 @@ extern int cgit_query_has_sha1; extern char *cgit_querystring; extern char *cgit_query_repo; extern char *cgit_query_page; extern char *cgit_query_search; extern char *cgit_query_head; extern char *cgit_query_sha1; extern char *cgit_query_sha2; extern char *cgit_query_path; extern char *cgit_query_name; extern int cgit_query_ofs; extern int htmlfd; extern void cgit_global_config_cb(const char *name, const char *value); extern void cgit_repo_config_cb(const char *name, const char *value); extern void cgit_querystring_cb(const char *name, const char *value); extern int chk_zero(int result, char *msg); extern int chk_positive(int result, char *msg); extern int hextoint(char c); extern void *cgit_free_commitinfo(struct commitinfo *info); +extern void cgit_diff_tree(const unsigned char *old_sha1, + const unsigned char *new_sha1, + filepair_fn fn); +extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); extern char *fmt(const char *format,...); extern void html(const char *txt); extern void htmlf(const char *format,...); extern void html_txt(char *txt); extern void html_ntxt(int len, char *txt); extern void html_attr(char *txt); extern void html_hidden(char *name, char *value); extern void html_link_open(char *url, char *title, char *class); extern void html_link_close(void); extern void html_filemode(unsigned short mode); extern int cgit_read_config(const char *filename, configfn fn); extern int cgit_parse_query(char *txt, configfn fn); extern struct commitinfo *cgit_parse_commit(struct commit *commit); extern struct taginfo *cgit_parse_tag(struct tag *tag); extern char *cache_safe_filename(const char *unsafe); extern int cache_lock(struct cacheitem *item); extern int cache_unlock(struct cacheitem *item); extern int cache_cancel_lock(struct cacheitem *item); extern int cache_exist(struct cacheitem *item); extern int cache_expired(struct cacheitem *item); @@ -53,50 +53,50 @@ int htmlfd = 0; int chk_zero(int result, char *msg) { if (result != 0) die("%s: %s", msg, strerror(errno)); return result; } int chk_positive(int result, char *msg) { if (result <= 0) die("%s: %s", msg, strerror(errno)); return result; } struct repoinfo *add_repo(const char *url) { struct repoinfo *ret; if (++cgit_repolist.count > cgit_repolist.length) { if (cgit_repolist.length == 0) cgit_repolist.length = 8; else cgit_repolist.length *= 2; - cgit_repolist.repos = xrealloc(cgit_repolist.repos, - cgit_repolist.length * + cgit_repolist.repos = xrealloc(cgit_repolist.repos, + cgit_repolist.length * sizeof(struct repoinfo)); } ret = &cgit_repolist.repos[cgit_repolist.count-1]; ret->url = xstrdup(url); ret->name = ret->url; ret->path = NULL; ret->desc = NULL; ret->owner = NULL; ret->snapshots = cgit_snapshots; ret->module_link = cgit_module_link; return ret; } void cgit_global_config_cb(const char *name, const char *value) { if (!strcmp(name, "root-title")) cgit_root_title = xstrdup(value); else if (!strcmp(name, "css")) cgit_css = xstrdup(value); else if (!strcmp(name, "logo")) cgit_logo = xstrdup(value); else if (!strcmp(name, "logo-link")) cgit_logo_link = xstrdup(value); @@ -174,24 +174,67 @@ void cgit_querystring_cb(const char *name, const char *value) void *cgit_free_commitinfo(struct commitinfo *info) { free(info->author); free(info->author_email); free(info->committer); free(info->committer_email); free(info->subject); free(info); return NULL; } int hextoint(char c) { if (c >= 'a' && c <= 'f') return 10 + c - 'a'; else if (c >= 'A' && c <= 'F') return 10 + c - 'A'; else if (c >= '0' && c <= '9') return c - '0'; else return -1; } +void cgit_diff_tree_cb(struct diff_queue_struct *q, + struct diff_options *options, void *data) +{ + int i; + + for (i = 0; i < q->nr; i++) { + if (q->queue[i]->status == 'U') + continue; + ((filepair_fn)data)(q->queue[i]); + } +} + +void cgit_diff_tree(const unsigned char *old_sha1, + const unsigned char *new_sha1, + filepair_fn fn) +{ + struct diff_options opt; + int ret; + + diff_setup(&opt); + opt.output_format = DIFF_FORMAT_CALLBACK; + opt.detect_rename = 1; + opt.recursive = 1; + opt.format_callback = cgit_diff_tree_cb; + opt.format_callback_data = fn; + diff_setup_done(&opt); + + if (old_sha1) + ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); + else + ret = diff_root_tree_sha1(new_sha1, "", &opt); + diffcore_std(&opt); + diff_flush(&opt); +} + +void cgit_diff_commit(struct commit *commit, filepair_fn fn) +{ + unsigned char *old_sha1 = NULL; + + if (commit->parents) + old_sha1 = commit->parents->item->object.sha1; + cgit_diff_tree(old_sha1, commit->object.sha1, fn); +} |