F diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
include_directories(${CMAKE_SOURCE_DIR})
set(SOURCES
git_part.c
+ system_part.c
volgit.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);
+ }
+ #endif
F 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);
+
+
+ #endif
F 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);