F diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txtinclude_directories(${CMAKE_SOURCE_DIR})set(SOURCESgit_part.c+ system_part.cvolgit.c)F diff --git a/git_part.c b/git_part.c --- a/git_part.c +++ b/git_part.c#define VOLGIT_GIT_PART_C VOLGIT_GIT_PART_C#include <git_part.h>- int print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const git_diff_line *line,void *payload)+ int print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const git_diff_line *line,FILE *out){size_t i;- printf("%c ",line->origin);+ fprintf(out,"%c ",line->origin);for(i=0;i<line->content_len;++i)- printf("%c",line->content[i]);+ fprintf(out,"%c",line->content[i]);return 0;}- void print_diff(git_tree *parent_tree,git_tree *current_tree,git_repository *repo)+ void print_diff(FILE *out,git_tree *parent_tree,git_tree *current_tree,git_repository *repo){git_diff *diff_from_parent;size_t number_of_deltas=0;git_diff_tree_to_tree(&diff_from_parent,repo,current_tree,parent_tree,NULL);- git_diff_print(diff_from_parent,GIT_DIFF_FORMAT_PATCH,print_diff_line,NULL);+ git_diff_print(diff_from_parent,GIT_DIFF_FORMAT_PATCH_ID,(git_diff_line_cb)print_diff_line,out);if(diff_from_parent)git_diff_free(diff_from_parent);}- void print_headers_and_commit_message(git_commit *current_commit,git_oid *current)+ void print_headers_and_commit_message(FILE *where,git_commit *current_commit,git_oid *current){const git_signature *who_commited;- printf("COMMIT: %s\n",git_oid_tostr_s(current));+ fprintf(where,"COMMIT: %s\n",git_oid_tostr_s(current));who_commited=git_commit_committer(current_commit);- printf("AUTHOR: %s <%s>\n",who_commited->name,who_commited->email);+ fprintf(where,"AUTHOR: %s <%s>\n",who_commited->name,who_commited->email);- printf("DATE: %s\n",ctime(&who_commited->when.time));+ fprintf(where,"DATE: %s\n",ctime(&who_commited->when.time));- printf("\t%s\n",git_commit_message(current_commit));+ fprintf(where,"\t%s\n",git_commit_message(current_commit));}- void print_commits(const git_reference *branch, git_repository *repo)+ void print_commits(int dir_fd,const git_reference *branch, git_repository *repo){const git_oid *id;+ FILE *log_file;+ FILE *diff_file;+ int diff_directory_fd;+git_revwalk *walker;git_oid current;git_commit *current_commit;git_revwalk_new(&walker,repo);id=git_reference_target(branch);git_revwalk_push(walker,id);+++ log_file=create_file(dir_fd,"log");+ diff_directory_fd=create_diff_dir(dir_fd);while(!git_revwalk_next(¤t,walker)){git_commit_tree(¤t_tree,current_commit);if(parent_tree!=NULL){- print_diff(parent_tree,current_tree,repo);+ diff_file=create_file(diff_directory_fd,git_oid_tostr_s(¤t));+ print_diff(diff_file,parent_tree,current_tree,repo);git_tree_free(parent_tree);}- print_headers_and_commit_message(current_commit,¤t);+ print_headers_and_commit_message(log_file,current_commit,¤t);parent_tree=current_tree;git_commit_free(current_commit);}-+ git_revwalk_free(walker);+ fclose(log_file);}void print_branches(git_repository *repo){const char *branch_name;+ int branch_dir_fd;git_branch_iterator *it;git_reference *ref;git_branch_t branch_type=GIT_BRANCH_LOCAL;git_branch_name(&branch_name,ref);if(branch_name){- printf("------- %s -------\n",branch_name);- print_commits(ref,repo);- printf("------------------\n");+ branch_dir_fd=create_branch_dir(branch_name);++ print_commits(branch_dir_fd,ref,repo);++ close(branch_dir_fd);}else{printf("NULL\n");F diff --git a/git_part.h b/git_part.h --- a/git_part.h +++ b/git_part.h#define VOLGIT_GIT_PART_H VOLGIT_GIT_PART_H#include <stdio.h>#include <git2.h>+ #include <system_part.h>- int print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const git_diff_line *line,void *payload);- void print_diff(git_tree *parent_tree,git_tree *current_tree,git_repository *repo);- void print_headers_and_commit_message(git_commit *current_commit,git_oid *current);- void print_commits(const git_reference *branch, git_repository *repo);+ int print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const git_diff_line *line,FILE *out);+ void print_diff(FILE *out,git_tree *parent_tree,git_tree *current_tree,git_repository *repo);+ void print_headers_and_commit_message(FILE* where,git_commit *current_commit,git_oid *current);+ void print_commits(int dir_fd,const git_reference *branch, git_repository *repo);void print_branches(git_repository *repo);F diff --git a/system_part.c b/system_part.c new file mode 100644 --- /dev/null +++ b/system_part.c+ #ifndef VOLGIT_SYSTEM_PART_C+ #define VOLGIT_SYSTEM_PART_C VOLGIT_SYSTEM_PART_C+ #include <system_part.h>++ const char *default_header="<!DOCTYPE html><html><head><title>GIT</title></head><body>";+ const char *default_footer="</body></html>";++ struct Volgit_Options options;++ void parse_options(int argc,char **argv)+ {++ options.header=default_header;+ options.footer=default_footer;+ switch(argc)+ {+ case 5:+ options.header=read_file(argv[3]);+ options.footer=read_file(argv[4]);+ /*falltrough*/+ case 3:+ options.input_path=argv[1];+ options.output_path=argv[2];+ break;+ default:+ die("Usage: volgit source destination [ file-containint-header file-containing-footer ]\n");+ }++ options.output_dir_fd=open(options.output_path,O_RDONLY|O_DIRECTORY);+ if(options.output_dir_fd==-1)+ {+ mkdir(options.output_path,0770);+ options.output_dir_fd=open(options.output_path,O_RDONLY|O_DIRECTORY);+ if(options.output_dir_fd==-1)+ die("Could not open output dir\n");+ }+ }+ char* read_file(const char *filename)+ {+ long file_size;+ int file;+ char *ret;+ struct stat file_stats;++ file=open(filename,O_RDONLY|O_CREAT);+ if(file==-1)+ die("Could not open file %s\n",filename);++ fstat(file,&file_stats);++ ret=malloc(file_stats.st_size+1);++ if(ret==NULL)+ die("Ran out of memory!\n");++ close(file);+ return ret;+ }++ int create_branch_dir(const char *branch_name)+ {+ int ret=0;++ ret=openat(options.output_dir_fd,branch_name,O_DIRECTORY|O_RDONLY);+ if(ret==-1)+ {+ if(mkdirat(options.output_dir_fd,branch_name,0770)==-1)+ die("Could not create branch directory for %s\n",branch_name);++ ret=openat(options.output_dir_fd,branch_name,O_DIRECTORY|O_RDONLY);+ if(ret==-1)+ die("Could not open newly created directory for branch %s\n",branch_name);+ }++ return ret;+ }+ FILE* create_file(int branch_dir,const char *filename)+ {+ int fd;+ unlinkat(branch_dir,filename,0);+ fd=openat(branch_dir,filename,O_CREAT|O_RDWR,0660);+ if(fd==-1)+ die("Could not open the file '%s' for one of the branches\n",filename);+ return fdopen(fd,"w");+ }+ int create_files_dir(int branch_dir)+ {+ int ret;++ ret=openat(branch_dir,"files",O_DIRECTORY|O_RDONLY);+ if(ret!=-1)+ return ret;++ ret=mkdirat(branch_dir,"files",0770);+ if(ret==-1)+ die("Could not create the 'files' subdirectory of one of the branch dirs\n");++ return ret;+ }+ int create_diff_dir(int branch_dir)+ {+ int ret;++ ret=openat(branch_dir,"diffs",O_DIRECTORY|O_RDONLY);+ if(ret!=-1)+ return ret;+ mkdirat(branch_dir,"diffs",0770);+ ret=openat(branch_dir,"diffs",O_DIRECTORY|O_RDONLY);+ if(ret==-1)+ die("Could not create the 'diffs' subdirectory of one of the branch dirs\n");+ return ret;+ }++ void die(const char *format, ...)+ {+ va_list args;+ va_start(args,format);+ vfprintf(stderr,format,args);+ exit(1);+ }+ #endifF diff --git a/system_part.h b/system_part.h new file mode 100644 --- /dev/null +++ b/system_part.h+ #ifndef VOLGIT_SYSTEM_PART_H+ #define VOLGIT_SYSTEM_PART_H VOLGIT_SYSTEM_PART_H+ #include <stdio.h>+ #include <stdlib.h>+ #include <unistd.h>+ #include <sys/stat.h>+ #include <fcntl.h>+ #include <stdarg.h>++ extern const char *default_header;+ extern const char *default_footer;++ extern struct Volgit_Options+ {+ const char *input_path;+ const char *output_path;+ const char *header;+ const char *footer;+ int output_dir_fd;+ }options;++ void die(const char *format, ...);++ void parse_options(int argc,char **argv);+ char* read_file(const char *filename);+ int create_branch_dir(const char *branch_name);+ FILE* create_file(int branch_dir,const char *filename);+ int create_files_dir(int branch_dir);+ int create_diff_dir(int branch_dir);+++ #endifF diff --git a/volgit.c b/volgit.c --- a/volgit.c +++ b/volgit.c#include <stdio.h>#include <git2.h>+ #include <system_part.h>#include <git_part.h>int main(int argc,char **argv){- const char *repo_path;-- if(argc<=1)- {- fprintf(stderr,"You need to specify a source dir for the repo\n");- return 1;- }git_repository *repo;git_libgit2_init();- git_repository_open(&repo,argv[1]);++ parse_options(argc,argv);++ git_repository_open(&repo,options.input_path);+ if(repo==NULL)+ die("Could not open input git repository\n");print_branches(repo);