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(const char *head
, const char *hex
, const char *prefix
,
73 const char *filename
, int snapshots
)
75 const struct snapshot_archive_t
* sat
;
76 struct archiver_args args
;
77 struct commit
*commit
;
78 unsigned char sha1
[20];
79 int f
, sl
, fnl
= strlen(filename
);
81 for(f
=0; f
<snapshot_archives_len
; f
++) {
82 sat
= &snapshot_archives
[f
];
83 if(!(snapshots
& sat
->bit
))
85 sl
= strlen(sat
->suffix
);
86 if(fnl
<sl
|| strcmp(&filename
[fnl
-sl
],sat
->suffix
))
90 if(get_sha1(hex
, sha1
)) {
91 cgit_print_error(fmt("Bad object id: %s", hex
));
94 commit
= lookup_commit_reference(sha1
);
96 cgit_print_error(fmt("Not a commit reference: %s", hex
));
99 memset(&args
,0,sizeof(args
));
100 args
.base
= fmt("%s/", prefix
);
101 args
.tree
= commit
->tree
;
102 args
.time
= commit
->date
;
103 ctx
.page
.mimetype
= xstrdup(sat
->mimetype
);
104 ctx
.page
.filename
= xstrdup(filename
);
105 cgit_print_http_headers(&ctx
);
106 (*sat
->write_func
)(&args
);
109 cgit_print_error(fmt("Unsupported snapshot format: %s", filename
));
112 void cgit_print_snapshot_links(const char *repo
, const char *head
,
113 const char *hex
, int snapshots
)
115 const struct snapshot_archive_t
* sat
;
119 for(f
=0; f
<snapshot_archives_len
; f
++) {
120 sat
= &snapshot_archives
[f
];
121 if(!(snapshots
& sat
->bit
))
123 filename
= fmt("%s-%s%s", cgit_repobasename(repo
), hex
,
125 cgit_snapshot_link(filename
, NULL
, NULL
, (char *)head
,
126 (char *)hex
, filename
);
131 int cgit_parse_snapshots_mask(const char *str
)
133 const struct snapshot_archive_t
* sat
;
134 static const char *delim
= " \t,:/|;";
135 int f
, tl
, sl
, rv
= 0;
137 /* favor legacy setting */
141 str
+= strspn(str
,delim
);
142 tl
= strcspn(str
,delim
);
145 for(f
=0; f
<snapshot_archives_len
; f
++) {
146 sat
= &snapshot_archives
[f
];
147 sl
= strlen(sat
->suffix
);
148 if((tl
== sl
&& !strncmp(sat
->suffix
, str
, tl
)) ||
149 (tl
== sl
-1 && !strncmp(sat
->suffix
+1, str
, tl
-1))) {