-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | cache.c | 8 | ||||
-rw-r--r-- | cgit.c | 8 | ||||
-rw-r--r-- | config.c | 8 | ||||
-rw-r--r-- | html.c | 8 |
5 files changed, 372 insertions, 0 deletions
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. @@ -1,86 +1,94 @@ +/* cache.c: cache management + * + * Copyright (C) 2006 Lars Hjemli + * + * Licensed under GNU General Public License v2 + * (see COPYING for full license text) + */ + #include "cgit.h" const int NOLOCK = -1; int cache_lookup(struct cacheitem *item) { if (!cgit_query_repo) { item->name = xstrdup(fmt("%s/index.html", cgit_cache_root)); item->ttl = cgit_cache_root_ttl; } else if (!cgit_query_page) { item->name = xstrdup(fmt("%s/%s/index.html", cgit_cache_root, cgit_query_repo)); item->ttl = cgit_cache_repo_ttl; } else { item->name = xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root, cgit_query_repo, cgit_query_page, cgit_querystring)); if (cgit_query_has_symref) item->ttl = cgit_cache_dynamic_ttl; else if (cgit_query_has_sha1) item->ttl = cgit_cache_static_ttl; else item->ttl = cgit_cache_repo_ttl; } if (stat(item->name, &item->st)) { item->st.st_mtime = 0; return 0; } return 1; } int cache_create_dirs() { char *path; if (!cgit_query_repo) return 0; path = fmt("%s/%s", cgit_cache_root, cgit_query_repo); if (mkdir(path, S_IRWXU) && errno!=EEXIST) return 0; if (cgit_query_page) { path = fmt("%s/%s/%s", cgit_cache_root, cgit_query_repo, cgit_query_page); if (mkdir(path, S_IRWXU) && errno!=EEXIST) return 0; } return 1; } int cache_lock(struct cacheitem *item) { int ret; char *lockfile = fmt("%s.lock", item->name); top: item->fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR|S_IWUSR); if (item->fd == NOLOCK && errno == ENOENT && cache_create_dirs()) goto top; if (item->fd == NOLOCK && errno == EEXIST) { struct stat st; time_t t; if (stat(lockfile, &st)) return ret; t = time(NULL); if (t-st.st_mtime > cgit_cache_max_create_time && !unlink(lockfile)) goto top; return 0; } return (item->fd > 0); } int cache_unlock(struct cacheitem *item) { close(item->fd); return (rename(fmt("%s.lock", item->name), item->name) == 0); } int cache_expired(struct cacheitem *item) { if (item->ttl < 0) return 0; return item->st.st_mtime + item->ttl * 60 < time(NULL); } @@ -1,384 +1,392 @@ +/* cgit.c: cgi for the git scm + * + * Copyright (C) 2006 Lars Hjemli + * + * Licensed under GNU General Public License v2 + * (see COPYING for full license text) + */ + #include "cgit.h" static const char cgit_doctype[] = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; static const char cgit_error[] = "<div class='error'>%s</div>"; static const char cgit_lib_error[] = "<div class='error'>%s: %s</div>"; int htmlfd = 0; char *cgit_root = "/usr/src/git"; char *cgit_root_title = "Git repository browser"; char *cgit_css = "/cgit.css"; char *cgit_logo = "/git-logo.png"; char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; char *cgit_virtual_root = NULL; char *cgit_cache_root = "/var/cache/cgit"; int cgit_cache_root_ttl = 5; int cgit_cache_repo_ttl = 5; int cgit_cache_dynamic_ttl = 5; int cgit_cache_static_ttl = -1; int cgit_cache_max_create_time = 5; char *cgit_repo_name = NULL; char *cgit_repo_desc = NULL; char *cgit_repo_owner = NULL; int cgit_query_has_symref = 0; int cgit_query_has_sha1 = 0; char *cgit_querystring = NULL; char *cgit_query_repo = NULL; char *cgit_query_page = NULL; char *cgit_query_head = NULL; char *cgit_query_sha1 = NULL; struct cacheitem cacheitem; int cgit_parse_query(char *txt, configfn fn) { char *t, *value = NULL, c; if (!txt) return 0; t = txt = xstrdup(txt); while((c=*t) != '\0') { if (c=='=') { *t = '\0'; value = t+1; } else if (c=='&') { *t = '\0'; (*fn)(txt, value); txt = t+1; value = NULL; } t++; } if (t!=txt) (*fn)(txt, value); return 0; } void cgit_global_config_cb(const char *name, const char *value) { if (!strcmp(name, "root")) cgit_root = xstrdup(value); else if (!strcmp(name, "root-title")) cgit_root_title = xstrdup(value); else if (!strcmp(name, "css")) cgit_css = xstrdup(value); else if (!strcmp(name, "logo")) cgit_logo = xstrdup(value); else if (!strcmp(name, "logo-link")) cgit_logo_link = xstrdup(value); else if (!strcmp(name, "virtual-root")) cgit_virtual_root = xstrdup(value); } void cgit_repo_config_cb(const char *name, const char *value) { if (!strcmp(name, "name")) cgit_repo_name = xstrdup(value); else if (!strcmp(name, "desc")) cgit_repo_desc = xstrdup(value); else if (!strcmp(name, "owner")) cgit_repo_owner = xstrdup(value); } void cgit_querystring_cb(const char *name, const char *value) { if (!strcmp(name,"r")) cgit_query_repo = xstrdup(value); else if (!strcmp(name, "p")) cgit_query_page = xstrdup(value); else if (!strcmp(name, "h")) { cgit_query_head = xstrdup(value); cgit_query_has_symref = 1; } else if (!strcmp(name, "id")) { cgit_query_sha1 = xstrdup(value); cgit_query_has_sha1 = 1; } } char *cgit_repourl(const char *reponame) { if (cgit_virtual_root) { return fmt("%s/%s/", cgit_virtual_root, reponame); } else { return fmt("?r=%s", reponame); } } char *cgit_pageurl(const char *reponame, const char *pagename, const char *query) { if (cgit_virtual_root) { return fmt("%s/%s/%s/?%s", cgit_virtual_root, reponame, pagename, query); } else { return fmt("?r=%s&p=%s&%s", reponame, pagename, query); } } static int cgit_print_branch_cb(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct commit *commit; char buf[256], *url; commit = lookup_commit(sha1); if (commit && !parse_commit(commit)){ html("<tr><td>"); url = cgit_pageurl(cgit_query_repo, "log", fmt("h=%s", refname)); html_link_open(url, NULL, NULL); strncpy(buf, refname, sizeof(buf)); html_txt(buf); html_link_close(); html("</td><td>"); pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, buf, sizeof(buf), 0, NULL, NULL, 0); html_txt(buf); html("</td></tr>\n"); } else { html("<tr><td>"); html_txt(buf); html("</td><td>"); htmlf("*** bad ref %s", sha1_to_hex(sha1)); html("</td></tr>\n"); } return 0; } /* Sun, 06 Nov 1994 08:49:37 GMT */ static char *http_date(time_t t) { static char day[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; struct tm *tm = gmtime(&t); return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); } static int ttl_seconds(int ttl) { if (ttl<0) return 60 * 60 * 24 * 365; else return ttl * 60; } static void cgit_print_docstart(char *title) { html("Content-Type: text/html; charset=utf-8\n"); htmlf("Last-Modified: %s\n", http_date(cacheitem.st.st_mtime)); htmlf("Expires: %s\n", http_date(cacheitem.st.st_mtime + ttl_seconds(cacheitem.ttl))); html("\n"); html(cgit_doctype); html("<html>\n"); html("<head>\n"); html("<title>"); html_txt(title); html("</title>\n"); html("<link rel='stylesheet' type='text/css' href='"); html_attr(cgit_css); html("'/>\n"); html("</head>\n"); html("<body>\n"); } static void cgit_print_docend() { html("</body>\n</html>\n"); } static void cgit_print_pageheader(char *title) { html("<div id='header'>"); htmlf("<a href='%s'>", cgit_logo_link); htmlf("<img id='logo' src='%s'/>\n", cgit_logo); htmlf("</a>"); html_txt(title); html("</div>"); } static void cgit_print_repolist() { DIR *d; struct dirent *de; struct stat st; char *name; chdir(cgit_root); cgit_print_docstart(cgit_root_title); cgit_print_pageheader(cgit_root_title); if (!(d = opendir("."))) { htmlf(cgit_lib_error, "Unable to scan repository directory", strerror(errno)); cgit_print_docend(); return; } html("<h2>Repositories</h2>\n"); html("<table class='list'>"); html("<tr><th>Name</th><th>Description</th><th>Owner</th></tr>\n"); while ((de = readdir(d)) != NULL) { if (de->d_name[0] == '.') continue; if (stat(de->d_name, &st) < 0) continue; if (!S_ISDIR(st.st_mode)) continue; cgit_repo_name = cgit_repo_desc = cgit_repo_owner = NULL; name = fmt("%s/info/cgit", de->d_name); if (cgit_read_config(name, cgit_repo_config_cb)) continue; html("<tr><td>"); html_link_open(cgit_repourl(de->d_name), NULL, NULL); html_txt(cgit_repo_name); html_link_close(); html("</td><td>"); html_txt(cgit_repo_desc); html("</td><td>"); html_txt(cgit_repo_owner); html("</td></tr>\n"); } closedir(d); html("</table>"); cgit_print_docend(); } static void cgit_print_branches() { html("<table class='list'>"); html("<tr><th>Branch name</th><th>Head commit</th></tr>\n"); for_each_branch_ref(cgit_print_branch_cb, NULL); html("</table>"); } static int get_one_line(char *txt) { char *t; for(t=txt; *t != '\n' && t != '\0'; t++) ; *t = '\0'; return t-txt-1; } static void cgit_print_commit_shortlog(struct commit *commit) { char *h, *t, *p; char *tree = NULL, *author = NULL, *subject = NULL; int len; time_t sec; struct tm *time; char buf[32]; h = t = commit->buffer; if (strncmp(h, "tree ", 5)) die("Bad commit format: %s", sha1_to_hex(commit->object.sha1)); len = get_one_line(h); tree = h+5; h += len + 2; while (!strncmp(h, "parent ", 7)) h += get_one_line(h) + 2; if (!strncmp(h, "author ", 7)) { author = h+7; h += get_one_line(h) + 2; t = author; while(t!=h && *t!='<') t++; *t='\0'; p = t; while(--t!=author && *t==' ') *t='\0'; while(++p!=h && *p!='>') ; while(++p!=h && !isdigit(*p)) ; t = p; while(++p && isdigit(*p)) ; *p = '\0'; sec = atoi(t); time = gmtime(&sec); } while((len = get_one_line(h)) > 0) h += len+2; h++; len = get_one_line(h); subject = h; html("<tr><td>"); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", time); html_txt(buf); html("</td><td>"); char *qry = fmt("id=%s", sha1_to_hex(commit->object.sha1)); char *url = cgit_pageurl(cgit_query_repo, "view", qry); html_link_open(url, NULL, NULL); html_txt(subject); html_link_close(); html("</td><td>"); html_txt(author); html("</td></tr>\n"); } static void cgit_print_log(const char *tip, int ofs, int cnt) { struct rev_info rev; struct commit *commit; const char *argv[2] = {NULL, tip}; int n = 0; init_revisions(&rev, NULL); rev.abbrev = DEFAULT_ABBREV; rev.commit_format = CMIT_FMT_DEFAULT; rev.verbose_header = 1; rev.show_root_diff = 0; setup_revisions(2, argv, &rev, NULL); prepare_revision_walk(&rev); html("<h2>Log</h2>"); html("<table class='list'>"); html("<tr><th>Date</th><th>Message</th><th>Author</th></tr>\n"); while ((commit = get_revision(&rev)) != NULL && n++ < 100) { cgit_print_commit_shortlog(commit); free(commit->buffer); commit->buffer = NULL; free_commit_list(commit->parents); commit->parents = NULL; } html("</table>\n"); } static void cgit_print_repo_summary() { html("<h2>"); html_txt("Repo summary page"); html("</h2>"); cgit_print_branches(); @@ -1,73 +1,81 @@ +/* config.c: parsing of config files + * + * Copyright (C) 2006 Lars Hjemli + * + * Licensed under GNU General Public License v2 + * (see COPYING for full license text) + */ + #include "cgit.h" int next_char(FILE *f) { int c = fgetc(f); if (c=='\r') { c = fgetc(f); if (c!='\n') { ungetc(c, f); c = '\r'; } } return c; } void skip_line(FILE *f) { int c; while((c=next_char(f)) && c!='\n' && c!=EOF) ; } int read_config_line(FILE *f, char *line, const char **value, int bufsize) { int i = 0, isname = 0; *value = NULL; while(i<bufsize-1) { int c = next_char(f); if (!isname && (c=='#' || c==';')) { skip_line(f); continue; } if (!isname && isspace(c)) continue; if (c=='=' && !*value) { line[i] = 0; *value = &line[i+1]; } else if (c=='\n' && !isname) { i = 0; continue; } else if (c=='\n' || c==EOF) { line[i] = 0; break; } else { line[i]=c; } isname = 1; i++; } line[i+1] = 0; return i; } int cgit_read_config(const char *filename, configfn fn) { int ret = 0, len; char line[256]; const char *value; FILE *f = fopen(filename, "r"); if (!f) return -1; while((len = read_config_line(f, line, &value, sizeof(line))) > 0) (*fn)(line, value); fclose(f); return ret; } @@ -1,102 +1,110 @@ +/* html.c: helper functions for html output + * + * Copyright (C) 2006 Lars Hjemli + * + * Licensed under GNU General Public License v2 + * (see COPYING for full license text) + */ + #include "cgit.h" char *fmt(const char *format, ...) { static char buf[8][1024]; static int bufidx; int len; va_list args; bufidx++; bufidx &= 7; va_start(args, format); len = vsnprintf(buf[bufidx], sizeof(buf[bufidx]), format, args); va_end(args); if (len>sizeof(buf[bufidx])) die("[html.c] string truncated: %s", format); return buf[bufidx]; } void html(const char *txt) { write(htmlfd, txt, strlen(txt)); } void htmlf(const char *format, ...) { static char buf[65536]; va_list args; va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); html(buf); } void html_txt(char *txt) { char *t = txt; while(*t){ int c = *t; if (c=='<' || c=='>' || c=='&') { *t = '\0'; html(txt); *t = c; if (c=='>') html(">"); else if (c=='<') html("<"); else if (c=='&') html("&"); txt = t+1; } t++; } if (t!=txt) html(txt); } void html_attr(char *txt) { char *t = txt; while(*t){ int c = *t; if (c=='<' || c=='>' || c=='\'') { *t = '\0'; html(txt); *t = c; if (c=='>') html(">"); else if (c=='<') html("<"); else if (c=='\'') html(""e;"); txt = t+1; } t++; } if (t!=txt) html(txt); } void html_link_open(char *url, char *title, char *class) { html("<a href='"); html_attr(url); if (title) { html("' title='"); html_attr(title); } if (class) { html("' class='"); html_attr(class); } html("'>"); } void html_link_close(void) { html("</a>"); } |