F diff --git a/git_part.c b/git_part.c --- a/git_part.c +++ b/git_part.cint print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const git_diff_line *line,FILE *out){size_t i;+ if(line->origin=='+')+ fprintf(out,"<div class=\"origin_added\">");+ else if(line->origin=='-')+ fprintf(out,"<div class=\"origin_removed\">");+ else+ fprintf(out,"<div class=\"origin_other\">");+fprintf(out,"%c ",line->origin);for(i=0;i<line->content_len;++i)fprintf(out,"%c",line->content[i]);++ fprintf(out,"</div>");+return 0;}size_t number_of_deltas=0;size_t i;- git_diff_tree_to_tree(&diff_from_parent,repo,current_tree,parent_tree,NULL);+ fprintf(out,"<pre>");+ git_diff_tree_to_tree(&diff_from_parent,repo,parent_tree,current_tree,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);+ fprintf(out,"</pre>");}- void print_headers_and_commit_message(FILE *where,git_commit *current_commit,git_oid *current)+ void print_headers_and_commit_message(FILE *where,git_commit *current_commit,const git_oid *current,_Bool has_diff){const git_signature *who_commited;- fprintf(where,"COMMIT: %s\n",git_oid_tostr_s(current));+ fprintf(where,"<div class=\"commit_header commit_commit_header\">COMMIT: %s",git_oid_tostr_s(current));+ if(has_diff)+ fprintf(where,"<a href=\"diffs/%s.html\"> [DIFF]</a></div>\n",git_oid_tostr_s(current));+ else+ fprintf(where,"</div>\n");who_commited=git_commit_committer(current_commit);- fprintf(where,"AUTHOR: %s <%s>\n",who_commited->name,who_commited->email);+ fprintf(where,"<div class=\"commit_header commit_author_header\">AUTHOR: %s <%s></div>\n",who_commited->name,who_commited->email);- fprintf(where,"DATE: %s\n",ctime(&who_commited->when.time));+ fprintf(where,"<div class=\"commit_header commit_date_header\">DATE: %s</div>\n",ctime(&who_commited->when.time));- fprintf(where,"\t%s\n",git_commit_message(current_commit));+ fprintf(where,"<pre><div class=\"commit_header commit_message\">\t%s</div></pre>\n",git_commit_message(current_commit));}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;int files_directory_fd;git_revwalk *walker;git_oid current;git_commit *current_commit;- git_time_t time_of_commit;- git_tree *parent_tree=NULL;- git_tree *current_tree;+ git_commit *parent_commit=NULL;git_revwalk_new(&walker,repo);id=git_reference_target(branch);diff_directory_fd=create_dir(dir_fd,"diffs");files_directory_fd=create_dir(dir_fd,"files");- while(!git_revwalk_next(¤t,walker))- {- git_commit_lookup(¤t_commit,repo,¤t);- git_commit_tree(¤t_tree,current_commit);+ if(git_revwalk_next(¤t,walker))+ return;- if(parent_tree!=NULL)- {- diff_file=create_file(diff_directory_fd,git_oid_tostr_s(¤t));+ git_commit_lookup(¤t_commit,repo,¤t);- print_diff(diff_file,parent_tree,current_tree,repo);+ print_files_top(files_directory_fd,current_commit,repo);- git_tree_free(parent_tree);- }else/*we only print the files of the HEAD*/- {- print_files(files_directory_fd,current_tree,repo);- }-- print_headers_and_commit_message(log_file,current_commit,¤t);+ while(!git_revwalk_next(¤t,walker))+ {+ git_commit_lookup(&parent_commit,repo,¤t);++ print_commit(current_commit,parent_commit,log_file,diff_directory_fd,repo);- parent_tree=current_tree;git_commit_free(current_commit);+ current_commit=parent_commit;}+ if(parent_commit!=NULL)+ print_commit(current_commit,NULL,log_file,diff_directory_fd,repo);git_revwalk_free(walker);fclose(log_file);}+ void print_commit(git_commit *current_commit,git_commit *parent_commit,FILE *log_file,int diff_directory_fd,git_repository *repo)+ {+ git_tree *current_tree;+ git_tree *parent_tree;+ FILE *diff_file;++ git_commit_tree(¤t_tree,current_commit);+ if(parent_commit==NULL)+ parent_tree=NULL;+ else+ git_commit_tree(&parent_tree,parent_commit);++ diff_file=create_file(diff_directory_fd,git_oid_tostr_s(git_commit_id(current_commit)));++ print_diff(diff_file,parent_tree,current_tree,repo);++ git_tree_free(parent_tree);+ print_headers_and_commit_message(log_file,current_commit,git_commit_id(current_commit),1);+ }void print_branches(git_repository *repo){size_t number_of_entries;size_t i;const git_tree_entry *current_entry;+ FILE *index_file;number_of_entries=git_tree_entrycount(tree);+ index_file=create_file(dir_fd,"index");for(i=0;i<number_of_entries;++i){current_entry=git_tree_entry_byindex(tree,i);- print_entry(current_entry,dir_fd,repo);+ print_entry(index_file,current_entry,dir_fd,repo);+ fprintf(index_file,"\n<br>\n");}}- int print_entry(const git_tree_entry *entry,int base_dir_fd,git_repository *repo)+ void print_files_top(int dir_fd,git_commit *top_commit,git_repository *repo)+ {+ git_tree *tree;++ git_commit_tree(&tree,top_commit);++ print_files(dir_fd,tree,repo);+ }+ int print_entry(FILE *index_file,const git_tree_entry *entry,int base_dir_fd,git_repository *repo){git_object *obj;+ const git_oid *obj_oid;const char *entry_name;+ const char *entry_oid;git_tree_entry_to_object(&obj,repo,entry);+ obj_oid=git_object_id(obj);+entry_name=git_tree_entry_name(entry);+ entry_oid=git_oid_tostr_s(obj_oid);switch(git_object_type(obj)){case GIT_OBJECT_TREE:+ push_html_link_for_tree(index_file,entry_name,entry_oid);{int new_dir_fd;git_tree *tree;tree=(git_tree*)obj;- new_dir_fd=create_dir(base_dir_fd,entry_name);+ new_dir_fd=create_dir(base_dir_fd,entry_oid);print_files(new_dir_fd,tree,repo);}break;case GIT_OBJECT_BLOB:+ push_html_link_for_blob(index_file,entry_name,entry_oid);{FILE *blob_file;const void *blob_data;blob=(git_blob*)obj;- blob_file=create_file(base_dir_fd,entry_name);+ blob_file=create_file(base_dir_fd,entry_oid);+blob_size=git_blob_rawsize(blob);blob_data=git_blob_rawcontent(blob);F diff --git a/git_part.h b/git_part.h --- a/git_part.h +++ b/git_part.h#include <git2.h>#include <system_part.h>-- struct Print_Files_Context- {- int base_dir_fd;- 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_headers_and_commit_message(FILE *where,git_commit *current_commit,const git_oid *current,_Bool has_diff);void print_commits(int dir_fd,const git_reference *branch, git_repository *repo);+ void print_commit(git_commit *current_commit,git_commit *parent_commit,FILE *log_file,int diff_directory_fd,git_repository *repo);+ void print_files_top(int dir_fd,git_commit *top_commit,git_repository *repo);void print_files(int dir_fd,git_tree *tree,git_repository *repo);- int print_entry(const git_tree_entry *entry,int base_dir_fd,git_repository *repo);+ int print_entry(FILE *index_file,const git_tree_entry *entry,int base_dir_fd,git_repository *repo);void print_branches(git_repository *repo);F diff --git a/system_part.c b/system_part.c --- a/system_part.c +++ b/system_part.cFILE* 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);+ char *new_filename;+ size_t old_filename_len;+ FILE *ret;++ old_filename_len=strlen(filename);+ new_filename=calloc(old_filename_len+sizeof(".html"),1);+ if(new_filename==NULL)+ die("Ran out of memory!\n");++ memcpy(new_filename,filename,old_filename_len);+ memcpy(new_filename+old_filename_len,".html",sizeof(".html"));++ unlinkat(branch_dir,new_filename,0);+ fd=openat(branch_dir,new_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");++ free(new_filename);++ ret=fdopen(fd,"w");++ fprintf(ret,"%s",options.header);+ return ret;+ }+ void close_file(FILE *file)+ {+ fprintf(file,"%s",options.footer);+ fclose(file);}int create_dir(int base_dir,const char *dir_name){vfprintf(stderr,format,args);exit(1);}+ void push_html_link_for_blob(FILE *out,const char *filename,const char *oid)+ {+ fprintf(out,"<a href=\"%s.html\" class=\"blob_entry\">%s</a>\n",oid,filename);+ }+ void push_html_link_for_tree(FILE *out,const char *filename,const char *oid)+ {+ fprintf(out,"<a href=\"%s/index.html\" class=\"tree_entry\">%s</a>\n",oid,filename);+ }#endifF diff --git a/system_part.h b/system_part.h --- a/system_part.h +++ b/system_part.h#include <sys/stat.h>#include <fcntl.h>#include <stdarg.h>+ #include <string.h>extern const char *default_header;extern const char *default_footer;char* read_file(const char *filename);int create_branch_dir(const char *branch_name);FILE* create_file(int branch_dir,const char *filename);+ void close_file(FILE *file);int create_dir(int base_dir,const char *dir_name);+ void push_html_link_for_blob(FILE *out,const char *filename,const char *oid);+ void push_html_link_for_tree(FILE *out,const char *filename,const char *oid);#endif