1 /* ui-snapshot.c: generate snapshot of a commit
3 * Copyright (C) 2006 Lars Hjemli
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
12 static int write_compressed_tar_archive(struct archiver_args
*args
,const char *filter
)
20 stdout2
= chk_non_negative(dup(STDIN_FILENO
), "Preserving STDOUT before compressing");
21 chk_zero(pipe(rw
), "Opening pipe from compressor subprocess");
22 gzpid
= chk_non_negative(fork(), "Forking compressor subprocess");
25 chk_zero(close(rw
[1]), "Closing write end of pipe in child");
26 chk_zero(close(STDIN_FILENO
), "Closing STDIN");
27 chk_non_negative(dup2(rw
[0],STDIN_FILENO
), "Redirecting compressor input to stdin");
28 execlp(filter
,filter
,NULL
);
32 chk_zero(close(rw
[0]), "Closing read end of pipe");
33 chk_non_negative(dup2(rw
[1],STDOUT_FILENO
), "Redirecting output to compressor");
35 rv
= write_tar_archive(args
);
37 chk_zero(close(STDOUT_FILENO
), "Closing STDOUT redirected to compressor");
38 chk_non_negative(dup2(stdout2
,STDOUT_FILENO
), "Restoring uncompressed STDOUT");
39 chk_zero(close(stdout2
), "Closing uncompressed STDOUT");
40 chk_zero(close(rw
[1]), "Closing write end of pipe in parent");
41 chk_positive(waitpid(gzpid
,&status
,0), "Waiting on compressor process");
42 if(! ( WIFEXITED(status
) && WEXITSTATUS(status
)==0 ) )
43 cgit_print_error("Failed to compress archive");
48 static int write_tar_gzip_archive(struct archiver_args
*args
)
50 return write_compressed_tar_archive(args
,"gzip");
53 static int write_tar_bzip2_archive(struct archiver_args
*args
)
55 return write_compressed_tar_archive(args
,"bzip2");
58 static const struct snapshot_archive_t
{
61 write_archive_fn_t write_func
;
63 } snapshot_archives
[] = {
64 { ".zip", "application/x-zip", write_zip_archive
, 0x1 },
65 { ".tar.gz", "application/x-tar", write_tar_gzip_archive
, 0x2 },
66 { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive
, 0x4 },
67 { ".tar", "application/x-tar", write_tar_archive
, 0x8 }
70 #define snapshot_archives_len (sizeof(snapshot_archives) / sizeof(*snapshot_archives))
72 void cgit_print_snapshot(struct cacheitem
*item
, const char *head
,
73 const char *hex
, const char *prefix
,
74 const char *filename
, int snapshots
)
76 const struct snapshot_archive_t
* sat
;
77 struct archiver_args args
;
78 struct commit
*commit
;
79 unsigned char sha1
[20];
80 int f
, sl
, fnl
= strlen(filename
);
82 for(f
=0; f
<snapshot_archives_len
; f
++) {
83 sat
= &snapshot_archives
[f
];
84 if(!(snapshots
& sat
->bit
))
86 sl
= strlen(sat
->suffix
);
87 if(fnl
<sl
|| strcmp(&filename
[fnl
-sl
],sat
->suffix
))
91 if(get_sha1(hex
, sha1
)) {
92 cgit_print_error(fmt("Bad object id: %s", hex
));
95 commit
= lookup_commit_reference(sha1
);
97 cgit_print_error(fmt("Not a commit reference: %s", hex
));
100 memset(&args
,0,sizeof(args
));
101 args
.base
= fmt("%s/", prefix
);
102 args
.tree
= commit
->tree
;
103 args
.time
= commit
->date
;
104 cgit_print_snapshot_start(sat
->mimetype
, filename
, item
);
105 (*sat
->write_func
)(&args
);
108 cgit_print_error(fmt("Unsupported snapshot format: %s", filename
));
111 void cgit_print_snapshot_links(const char *repo
, const char *head
,
112 const char *hex
, int snapshots
)
114 const struct snapshot_archive_t
* sat
;
118 for(f
=0; f
<snapshot_archives_len
; f
++) {
119 sat
= &snapshot_archives
[f
];
120 if(!(snapshots
& sat
->bit
))
122 filename
= fmt("%s-%s%s", cgit_repobasename(repo
), hex
,
124 cgit_snapshot_link(filename
, NULL
, NULL
, (char *)head
,
125 (char *)hex
, filename
);
130 int cgit_parse_snapshots_mask(const char *str
)
132 const struct snapshot_archive_t
* sat
;
133 static const char *delim
= " \t,:/|;";
134 int f
, tl
, sl
, rv
= 0;
136 /* favor legacy setting */
140 str
+= strspn(str
,delim
);
141 tl
= strcspn(str
,delim
);
144 for(f
=0; f
<snapshot_archives_len
; f
++) {
145 sat
= &snapshot_archives
[f
];
146 sl
= strlen(sat
->suffix
);
147 if((tl
== sl
&& !strncmp(sat
->suffix
, str
, tl
)) ||
148 (tl
== sl
-1 && !strncmp(sat
->suffix
+1, str
, tl
-1))) {