summaryrefslogtreecommitdiffstats
path: root/git_part.c
diff options
context:
space:
mode:
Diffstat (limited to 'git_part.c')
-rw-r--r--git_part.c218
1 files changed, 163 insertions, 55 deletions
diff --git a/git_part.c b/git_part.c
index 0355ec2..5f2fe7b 100644
--- a/git_part.c
+++ b/git_part.c
@@ -12,6 +12,21 @@ static const char *special_chars[256]
['>']=">",
};
+struct Index_File *get_index_file(int dir_fd,const char *name)
+{
+ struct Index_File *ret;
+ ret=calloc(sizeof(struct Index_File),1);
+ ret->out=create_file(dir_fd,name);
+
+ fprintf(ret->out,"<pre>\n");
+ return ret;
+}
+void release_index_file(struct Index_File *index)
+{
+ fprintf(index->out,"</pre>\n");
+ close_file(index->out);
+ free(index);
+}
int print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const git_diff_line *line,FILE *out)
{
@@ -25,9 +40,9 @@ int print_diff_line(const git_diff_delta *delta,const git_diff_hunk *hunk,const
fprintf(out,"%c ",line->origin);
for(i=0;i<line->content_len;++i)
- if(special_chars[line->content[i]])
+ if(special_chars[(unsigned char)line->content[i]])
{
- fwrite(special_chars[line->content[i]],1,strlen(special_chars[line->content[i]]),out);
+ fwrite(special_chars[line->content[i]],1,strlen(special_chars[(unsigned char)line->content[i]]),out);
}else
{
fwrite(line->content+i,1,1,out);
@@ -162,95 +177,188 @@ void print_branches(git_repository *repo)
git_branch_iterator_free(it);
}
-void print_files(int dir_fd,git_tree *tree,git_repository *repo)
+void print_files(struct Index_File *index_file,int dir_fd,git_tree *tree,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);
+
+ if(i<number_of_entries-1)
+ indentation_set_is_not_final(index_file,1);
+ else
+ indentation_set_is_not_final(index_file,0);
+
+
+ if(state.output_is_tree_like)
+ {
+ print_indentation_for_treelike_output(index_file);
+ if(i<number_of_entries-1)
+ fprintf(index_file->out,"├── ");
+ else
+ fprintf(index_file->out,"└── ");
+ }
print_entry(index_file,current_entry,dir_fd,repo);
- fprintf(index_file,"\n<br>\n");
+ if(i<number_of_entries-1)
+ fprintf(index_file->out,"\n");
}
- close_file(index_file);
}
void print_files_top(int dir_fd,git_commit *top_commit,git_repository *repo)
{
+ struct Index_File *index_file;
git_tree *tree;
git_commit_tree(&tree,top_commit);
- print_files(dir_fd,tree,repo);
+ index_file=get_index_file(dir_fd,"index");
+
+ if(state.output_is_tree_like)
+ fprintf(index_file->out,"|\n");
+
+ print_files(index_file,dir_fd,tree,repo);
+
+
+ release_index_file(index_file);
}
-int print_entry(FILE *index_file,const git_tree_entry *entry,int base_dir_fd,git_repository *repo)
+int print_entry(struct Index_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_oid);
- print_files(new_dir_fd,tree,repo);
- }
+ print_tree_entry(index_file,entry_name,obj,base_dir_fd,repo);
break;
case GIT_OBJECT_BLOB:
- push_html_link_for_blob(index_file,entry_name,entry_oid);
- {
- FILE *blob_file;
- const unsigned char *blob_data;
- size_t blob_size;
- size_t i;
- git_blob *blob;
-
-
- blob=(git_blob*)obj;
-
- blob_file=create_file(base_dir_fd,entry_oid);
-
- blob_size=git_blob_rawsize(blob);
- blob_data=git_blob_rawcontent(blob);
-
- fprintf(blob_file,"<code><pre>\n");
- for(i=0;i<blob_size;++i)
- {
- if(special_chars[blob_data[i]])
- {
- fwrite(special_chars[blob_data[i]],1,strlen(special_chars[blob_data[i]]),blob_file);
- }else
- {
- fwrite(blob_data+i,1,1,blob_file);
- }
- }
- fprintf(blob_file,"</pre></code>\n");
-
- close_file(blob_file);
- }
+ print_blob_entry(index_file,entry_name,obj,base_dir_fd,repo);
break;
}
git_object_free(obj);
return 0;
}
+static inline void print_tree_entry(struct Index_File *index_file,const char *name,git_object *obj,int base_dir_fd,git_repository *repo)
+{
+ const git_oid *obj_oid;
+ const char *entry_oid;
+ git_tree *tree;
+
+ obj_oid=git_object_id(obj);
+ entry_oid=git_oid_tostr_s(obj_oid);
+ tree=(git_tree*)obj;
+
+
+
+ if(state.output_is_tree_like)
+ {
+ if(index_file->indentation==state.tree_cutoff)
+ {
+ push_html_link_for_tree(index_file->out,name,entry_oid);
+ print_files_in_another_index(base_dir_fd,entry_oid,name,tree,repo);
+
+ }else
+ {
+ fprintf(index_file->out,"%s ─┐",name);
+ increment_indentation(index_file,name);
+
+ fprintf(index_file->out,"\n");
+ print_files(index_file,base_dir_fd,tree,repo);
+
+ decrement_indentation(index_file);
+ }
+ }else
+ {
+ push_html_link_for_tree(index_file->out,name,entry_oid);
+ print_files_in_another_index(base_dir_fd,entry_oid,name,tree,repo);
+ }
+}
+static inline void print_blob_entry(struct Index_File *index_file,const char *name,git_object *obj,int base_dir_fd,git_repository *repo)
+{
+ const git_oid *obj_oid;
+ const char *entry_oid;
+
+ FILE *blob_file;
+ const unsigned char *blob_data;
+ size_t blob_size;
+ size_t i;
+ git_blob *blob;
+
+ obj_oid=git_object_id(obj);
+ entry_oid=git_oid_tostr_s(obj_oid);
+
+ push_html_link_for_blob(index_file->out,name,entry_oid);
+
+ blob=(git_blob*)obj;
+ blob_file=create_file(base_dir_fd,entry_oid);
+
+ blob_size=git_blob_rawsize(blob);
+ blob_data=git_blob_rawcontent(blob);
+
+ fprintf(blob_file,"<code><pre>\n");
+ for(i=0;i<blob_size;++i)
+ {
+ if(special_chars[blob_data[i]])
+ {
+ fwrite(special_chars[blob_data[i]],1,strlen(special_chars[blob_data[i]]),blob_file);
+ }else
+ {
+ fwrite(blob_data+i,1,1,blob_file);
+ }
+ }
+ fprintf(blob_file,"</pre></code>\n");
+
+ close_file(blob_file);
+}
+void print_indentation_for_treelike_output(struct Index_File *out)
+{
+ int i;
+ int j;
+ for(i=0;i<out->indentation;++i)
+ {
+ if(out->branches[i])
+ fprintf(out->out,"|");
+ else
+ fprintf(out->out," ");
+
+ for(j=0;j<out->offset[i]+5;++j)
+ fprintf(out->out," ");
+ }
+}
+void increment_indentation(struct Index_File *index,const char *name)
+{
+ index->offset[index->indentation]=strnlen(name,1000);
+ ++index->indentation;
+}
+void decrement_indentation(struct Index_File *index)
+{
+ --index->indentation;
+}
+void indentation_set_is_not_final(struct Index_File *index,_Bool is_final)
+{
+ index->branches[index->indentation]=is_final;
+}
+
+void print_files_in_another_index(int base_dir_fd,const char *entry_oid,const char *name,git_tree *tree,git_repository *repo)
+{
+ int new_dir_fd;
+ struct Index_File *new_index;
+
+ new_dir_fd=create_dir(base_dir_fd,entry_oid);
+ new_index=get_index_file(new_dir_fd,"index");
+ if(state.output_is_tree_like)
+ fprintf(new_index->out,"%s\n|\n",name);
+ print_files(new_index,new_dir_fd,tree,repo);
+
+ release_index_file(new_index);
+ close(new_dir_fd);
+}
#endif