summaryrefslogtreecommitdiffabout
path: root/ui-shared.c
Unidiff
Diffstat (limited to 'ui-shared.c') (more/less context) (ignore whitespace changes)
-rw-r--r--ui-shared.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/ui-shared.c b/ui-shared.c
index 3e13c86..ece041c 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -271,275 +271,292 @@ void cgit_diff_link(char *name, char *title, char *class, char *head,
271 html_txt(name); 271 html_txt(name);
272 html("</a>"); 272 html("</a>");
273} 273}
274 274
275void cgit_object_link(struct object *obj) 275void cgit_object_link(struct object *obj)
276{ 276{
277 char *page, *arg, *url; 277 char *page, *arg, *url;
278 278
279 if (obj->type == OBJ_COMMIT) { 279 if (obj->type == OBJ_COMMIT) {
280 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL, 280 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL,
281 cgit_query_head, sha1_to_hex(obj->sha1)); 281 cgit_query_head, sha1_to_hex(obj->sha1));
282 return; 282 return;
283 } else if (obj->type == OBJ_TREE) { 283 } else if (obj->type == OBJ_TREE) {
284 page = "tree"; 284 page = "tree";
285 arg = "id"; 285 arg = "id";
286 } else if (obj->type == OBJ_TAG) { 286 } else if (obj->type == OBJ_TAG) {
287 page = "tag"; 287 page = "tag";
288 arg = "id"; 288 arg = "id";
289 } else { 289 } else {
290 page = "blob"; 290 page = "blob";
291 arg = "id"; 291 arg = "id";
292 } 292 }
293 293
294 url = cgit_pageurl(cgit_query_repo, page, 294 url = cgit_pageurl(cgit_query_repo, page,
295 fmt("%s=%s", arg, sha1_to_hex(obj->sha1))); 295 fmt("%s=%s", arg, sha1_to_hex(obj->sha1)));
296 html_link_open(url, NULL, NULL); 296 html_link_open(url, NULL, NULL);
297 htmlf("%s %s", typename(obj->type), 297 htmlf("%s %s", typename(obj->type),
298 sha1_to_hex(obj->sha1)); 298 sha1_to_hex(obj->sha1));
299 html_link_close(); 299 html_link_close();
300} 300}
301 301
302void cgit_print_date(time_t secs, char *format) 302void cgit_print_date(time_t secs, char *format)
303{ 303{
304 char buf[64]; 304 char buf[64];
305 struct tm *time; 305 struct tm *time;
306 306
307 if (!secs) 307 if (!secs)
308 return; 308 return;
309 time = gmtime(&secs); 309 time = gmtime(&secs);
310 strftime(buf, sizeof(buf)-1, format, time); 310 strftime(buf, sizeof(buf)-1, format, time);
311 html_txt(buf); 311 html_txt(buf);
312} 312}
313 313
314void cgit_print_age(time_t t, time_t max_relative, char *format) 314void cgit_print_age(time_t t, time_t max_relative, char *format)
315{ 315{
316 time_t now, secs; 316 time_t now, secs;
317 317
318 if (!t) 318 if (!t)
319 return; 319 return;
320 time(&now); 320 time(&now);
321 secs = now - t; 321 secs = now - t;
322 322
323 if (secs > max_relative && max_relative >= 0) { 323 if (secs > max_relative && max_relative >= 0) {
324 cgit_print_date(t, format); 324 cgit_print_date(t, format);
325 return; 325 return;
326 } 326 }
327 327
328 if (secs < TM_HOUR * 2) { 328 if (secs < TM_HOUR * 2) {
329 htmlf("<span class='age-mins'>%.0f min.</span>", 329 htmlf("<span class='age-mins'>%.0f min.</span>",
330 secs * 1.0 / TM_MIN); 330 secs * 1.0 / TM_MIN);
331 return; 331 return;
332 } 332 }
333 if (secs < TM_DAY * 2) { 333 if (secs < TM_DAY * 2) {
334 htmlf("<span class='age-hours'>%.0f hours</span>", 334 htmlf("<span class='age-hours'>%.0f hours</span>",
335 secs * 1.0 / TM_HOUR); 335 secs * 1.0 / TM_HOUR);
336 return; 336 return;
337 } 337 }
338 if (secs < TM_WEEK * 2) { 338 if (secs < TM_WEEK * 2) {
339 htmlf("<span class='age-days'>%.0f days</span>", 339 htmlf("<span class='age-days'>%.0f days</span>",
340 secs * 1.0 / TM_DAY); 340 secs * 1.0 / TM_DAY);
341 return; 341 return;
342 } 342 }
343 if (secs < TM_MONTH * 2) { 343 if (secs < TM_MONTH * 2) {
344 htmlf("<span class='age-weeks'>%.0f weeks</span>", 344 htmlf("<span class='age-weeks'>%.0f weeks</span>",
345 secs * 1.0 / TM_WEEK); 345 secs * 1.0 / TM_WEEK);
346 return; 346 return;
347 } 347 }
348 if (secs < TM_YEAR * 2) { 348 if (secs < TM_YEAR * 2) {
349 htmlf("<span class='age-months'>%.0f months</span>", 349 htmlf("<span class='age-months'>%.0f months</span>",
350 secs * 1.0 / TM_MONTH); 350 secs * 1.0 / TM_MONTH);
351 return; 351 return;
352 } 352 }
353 htmlf("<span class='age-years'>%.0f years</span>", 353 htmlf("<span class='age-years'>%.0f years</span>",
354 secs * 1.0 / TM_YEAR); 354 secs * 1.0 / TM_YEAR);
355} 355}
356 356
357void cgit_print_docstart(char *title, struct cacheitem *item) 357void cgit_print_docstart(char *title, struct cacheitem *item)
358{ 358{
359 html("Content-Type: text/html; charset=" PAGE_ENCODING "\n"); 359 html("Content-Type: text/html; charset=" PAGE_ENCODING "\n");
360 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); 360 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime));
361 htmlf("Expires: %s\n", http_date(item->st.st_mtime + 361 htmlf("Expires: %s\n", http_date(item->st.st_mtime +
362 ttl_seconds(item->ttl))); 362 ttl_seconds(item->ttl)));
363 html("\n"); 363 html("\n");
364 html(cgit_doctype); 364 html(cgit_doctype);
365 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); 365 html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n");
366 html("<head>\n"); 366 html("<head>\n");
367 html("<title>"); 367 html("<title>");
368 html_txt(title); 368 html_txt(title);
369 html("</title>\n"); 369 html("</title>\n");
370 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version); 370 htmlf("<meta name='generator' content='cgit %s'/>\n", cgit_version);
371 if (cgit_robots && *cgit_robots) 371 if (cgit_robots && *cgit_robots)
372 htmlf("<meta name='robots' content='%s'/>\n", cgit_robots); 372 htmlf("<meta name='robots' content='%s'/>\n", cgit_robots);
373 html("<link rel='stylesheet' type='text/css' href='"); 373 html("<link rel='stylesheet' type='text/css' href='");
374 html_attr(cgit_css); 374 html_attr(cgit_css);
375 html("'/>\n"); 375 html("'/>\n");
376 html("</head>\n"); 376 html("</head>\n");
377 html("<body>\n"); 377 html("<body>\n");
378} 378}
379 379
380void cgit_print_docend() 380void cgit_print_docend()
381{ 381{
382 html("</td>\n</tr>\n</table>\n</body>\n</html>\n"); 382 html("</td>\n</tr>\n</table>\n</body>\n</html>\n");
383} 383}
384 384
385int print_branch_option(const char *refname, const unsigned char *sha1, 385int print_branch_option(const char *refname, const unsigned char *sha1,
386 int flags, void *cb_data) 386 int flags, void *cb_data)
387{ 387{
388 char *name = (char *)refname; 388 char *name = (char *)refname;
389 html_option(name, name, cgit_query_head); 389 html_option(name, name, cgit_query_head);
390 return 0; 390 return 0;
391} 391}
392 392
393int print_archive_ref(const char *refname, const unsigned char *sha1, 393int print_archive_ref(const char *refname, const unsigned char *sha1,
394 int flags, void *cb_data) 394 int flags, void *cb_data)
395{ 395{
396 struct tag *tag; 396 struct tag *tag;
397 struct taginfo *info; 397 struct taginfo *info;
398 struct object *obj; 398 struct object *obj;
399 char buf[256], *url; 399 char buf[256], *url;
400 unsigned char fileid[20]; 400 unsigned char fileid[20];
401 int *header = (int *)cb_data; 401 int *header = (int *)cb_data;
402 402
403 if (prefixcmp(refname, "refs/archives")) 403 if (prefixcmp(refname, "refs/archives"))
404 return 0; 404 return 0;
405 strncpy(buf, refname+14, sizeof(buf)); 405 strncpy(buf, refname+14, sizeof(buf));
406 obj = parse_object(sha1); 406 obj = parse_object(sha1);
407 if (!obj) 407 if (!obj)
408 return 1; 408 return 1;
409 if (obj->type == OBJ_TAG) { 409 if (obj->type == OBJ_TAG) {
410 tag = lookup_tag(sha1); 410 tag = lookup_tag(sha1);
411 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 411 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
412 return 0; 412 return 0;
413 hashcpy(fileid, tag->tagged->sha1); 413 hashcpy(fileid, tag->tagged->sha1);
414 } else if (obj->type != OBJ_BLOB) { 414 } else if (obj->type != OBJ_BLOB) {
415 return 0; 415 return 0;
416 } else { 416 } else {
417 hashcpy(fileid, sha1); 417 hashcpy(fileid, sha1);
418 } 418 }
419 if (!*header) { 419 if (!*header) {
420 html("<h1>download</h1>\n"); 420 html("<h1>download</h1>\n");
421 *header = 1; 421 *header = 1;
422 } 422 }
423 url = cgit_pageurl(cgit_query_repo, "blob", 423 url = cgit_pageurl(cgit_query_repo, "blob",
424 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid), 424 fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
425 buf)); 425 buf));
426 html_link_open(url, NULL, "menu"); 426 html_link_open(url, NULL, "menu");
427 html_txt(strlpart(buf, 20)); 427 html_txt(strlpart(buf, 20));
428 html_link_close(); 428 html_link_close();
429 return 0; 429 return 0;
430} 430}
431 431
432void add_hidden_formfields(int incl_head, int incl_search, char *page) 432void add_hidden_formfields(int incl_head, int incl_search, char *page)
433{ 433{
434 char *url; 434 char *url;
435 435
436 if (!cgit_virtual_root) { 436 if (!cgit_virtual_root) {
437 url = fmt("%s/%s", cgit_query_repo, page); 437 url = fmt("%s/%s", cgit_query_repo, page);
438 if (cgit_query_path) 438 if (cgit_query_path)
439 url = fmt("%s/%s", url, cgit_query_path); 439 url = fmt("%s/%s", url, cgit_query_path);
440 html_hidden("url", url); 440 html_hidden("url", url);
441 } 441 }
442 442
443 if (incl_head && strcmp(cgit_query_head, cgit_repo->defbranch)) 443 if (incl_head && strcmp(cgit_query_head, cgit_repo->defbranch))
444 html_hidden("h", cgit_query_head); 444 html_hidden("h", cgit_query_head);
445 445
446 if (cgit_query_sha1) 446 if (cgit_query_sha1)
447 html_hidden("id", cgit_query_sha1); 447 html_hidden("id", cgit_query_sha1);
448 if (cgit_query_sha2) 448 if (cgit_query_sha2)
449 html_hidden("id2", cgit_query_sha2); 449 html_hidden("id2", cgit_query_sha2);
450 450
451 if (incl_search) { 451 if (incl_search) {
452 if (cgit_query_grep) 452 if (cgit_query_grep)
453 html_hidden("qt", cgit_query_grep); 453 html_hidden("qt", cgit_query_grep);
454 if (cgit_query_search) 454 if (cgit_query_search)
455 html_hidden("q", cgit_query_search); 455 html_hidden("q", cgit_query_search);
456 } 456 }
457} 457}
458 458
459void cgit_print_pageheader(char *title, int show_search) 459void cgit_print_pageheader(char *title, int show_search)
460{ 460{
461 static const char *default_info = "This is cgit, a fast webinterface for git repositories"; 461 static const char *default_info = "This is cgit, a fast webinterface for git repositories";
462 int header = 0; 462 int header = 0;
463 char *url;
463 464
464 html("<table id='layout' summary=''>\n"); 465 html("<table id='layout' summary=''>\n");
465 html("<tr><td id='sidebar'>\n"); 466 html("<tr><td id='sidebar'>\n");
466 html("<table class='sidebar' cellspacing='0' summary=''>\n"); 467 html("<table class='sidebar' cellspacing='0' summary=''>\n");
467 html("<tr><td class='sidebar'>\n<a href='"); 468 html("<tr><td class='sidebar'>\n<a href='");
468 html_attr(cgit_rooturl()); 469 html_attr(cgit_rooturl());
469 htmlf("'><img src='%s' alt='cgit'/></a>\n", 470 htmlf("'><img src='%s' alt='cgit'/></a>\n",
470 cgit_logo); 471 cgit_logo);
471 html("</td></tr>\n<tr><td class='sidebar'>\n"); 472 html("</td></tr>\n<tr><td class='sidebar'>\n");
472 if (cgit_query_repo) { 473 if (cgit_query_repo) {
473 html("<h1 class='first'>"); 474 html("<h1 class='first'>");
474 html_txt(strrpart(cgit_repo->name, 20)); 475 html_txt(strrpart(cgit_repo->name, 20));
475 html("</h1>\n"); 476 html("</h1>\n");
476 html_txt(cgit_repo->desc); 477 html_txt(cgit_repo->desc);
477 if (cgit_repo->owner) { 478 if (cgit_repo->owner) {
478 html("<h1>owner</h1>\n"); 479 html("<h1>owner</h1>\n");
479 html_txt(cgit_repo->owner); 480 html_txt(cgit_repo->owner);
480 } 481 }
481 html("<h1>navigate</h1>\n"); 482 html("<h1>navigate</h1>\n");
482 reporevlink(NULL, "summary", NULL, "menu", cgit_query_head, 483 reporevlink(NULL, "summary", NULL, "menu", cgit_query_head,
483 NULL, NULL); 484 NULL, NULL);
484 cgit_log_link("log", NULL, "menu", cgit_query_head, NULL, NULL, 485 cgit_log_link("log", NULL, "menu", cgit_query_head, NULL, NULL,
485 0, NULL, NULL); 486 0, NULL, NULL);
486 cgit_tree_link("tree", NULL, "menu", cgit_query_head, 487 cgit_tree_link("tree", NULL, "menu", cgit_query_head,
487 cgit_query_sha1, NULL); 488 cgit_query_sha1, NULL);
488 cgit_commit_link("commit", NULL, "menu", cgit_query_head, 489 cgit_commit_link("commit", NULL, "menu", cgit_query_head,
489 cgit_query_sha1); 490 cgit_query_sha1);
490 cgit_diff_link("diff", NULL, "menu", cgit_query_head, 491 cgit_diff_link("diff", NULL, "menu", cgit_query_head,
491 cgit_query_sha1, cgit_query_sha2, NULL); 492 cgit_query_sha1, cgit_query_sha2, NULL);
492 493
493 for_each_ref(print_archive_ref, &header); 494 for_each_ref(print_archive_ref, &header);
494 495
496 if (cgit_repo->clone_url || cgit_clone_prefix) {
497 html("<h1>clone</h1>\n");
498 if (cgit_repo->clone_url)
499 url = cgit_repo->clone_url;
500 else
501 url = fmt("%s%s", cgit_clone_prefix,
502 cgit_repo->url);
503 html("<a class='menu' href='");
504 html_attr(url);
505 html("' title='");
506 html_attr(url);
507 html("'>\n");
508 html_txt(strrpart(url, 20));
509 html("</a>\n");
510 }
511
495 html("<h1>branch</h1>\n"); 512 html("<h1>branch</h1>\n");
496 html("<form method='get' action=''>\n"); 513 html("<form method='get' action=''>\n");
497 add_hidden_formfields(0, 1, cgit_query_page); 514 add_hidden_formfields(0, 1, cgit_query_page);
498 // html("<table summary='branch selector' class='grid'><tr><td id='branch-dropdown-cell'>"); 515 // html("<table summary='branch selector' class='grid'><tr><td id='branch-dropdown-cell'>");
499 html("<select name='h' onchange='this.form.submit();'>\n"); 516 html("<select name='h' onchange='this.form.submit();'>\n");
500 for_each_branch_ref(print_branch_option, cgit_query_head); 517 for_each_branch_ref(print_branch_option, cgit_query_head);
501 html("</select>\n"); 518 html("</select>\n");
502 // html("</td><td>"); 519 // html("</td><td>");
503 html("<noscript><input type='submit' id='switch-btn' value='switch'/></noscript>\n"); 520 html("<noscript><input type='submit' id='switch-btn' value='switch'/></noscript>\n");
504 // html("</td></tr></table>"); 521 // html("</td></tr></table>");
505 html("</form>\n"); 522 html("</form>\n");
506 523
507 html("<h1>search</h1>\n"); 524 html("<h1>search</h1>\n");
508 html("<form method='get' action='"); 525 html("<form method='get' action='");
509 if (cgit_virtual_root) 526 if (cgit_virtual_root)
510 html_attr(cgit_fileurl(cgit_query_repo, "log", 527 html_attr(cgit_fileurl(cgit_query_repo, "log",
511 cgit_query_path, NULL)); 528 cgit_query_path, NULL));
512 html("'>\n"); 529 html("'>\n");
513 add_hidden_formfields(1, 0, "log"); 530 add_hidden_formfields(1, 0, "log");
514 html("<select name='qt'>\n"); 531 html("<select name='qt'>\n");
515 html_option("grep", "log msg", cgit_query_grep); 532 html_option("grep", "log msg", cgit_query_grep);
516 html_option("author", "author", cgit_query_grep); 533 html_option("author", "author", cgit_query_grep);
517 html_option("committer", "committer", cgit_query_grep); 534 html_option("committer", "committer", cgit_query_grep);
518 html("</select>\n"); 535 html("</select>\n");
519 html("<input class='txt' type='text' name='q' value='"); 536 html("<input class='txt' type='text' name='q' value='");
520 html_attr(cgit_query_search); 537 html_attr(cgit_query_search);
521 html("'/>\n"); 538 html("'/>\n");
522 html("</form>\n"); 539 html("</form>\n");
523 } else { 540 } else {
524 if (!cgit_index_info || html_include(cgit_index_info)) 541 if (!cgit_index_info || html_include(cgit_index_info))
525 html(default_info); 542 html(default_info);
526 } 543 }
527 544
528 html("</td></tr></table></td>\n"); 545 html("</td></tr></table></td>\n");
529 546
530 html("<td id='content'>\n"); 547 html("<td id='content'>\n");
531} 548}
532 549
533 550
534void cgit_print_snapshot_start(const char *mimetype, const char *filename, 551void cgit_print_snapshot_start(const char *mimetype, const char *filename,
535 struct cacheitem *item) 552 struct cacheitem *item)
536{ 553{
537 htmlf("Content-Type: %s\n", mimetype); 554 htmlf("Content-Type: %s\n", mimetype);
538 htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename); 555 htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename);
539 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); 556 htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime));
540 htmlf("Expires: %s\n", http_date(item->st.st_mtime + 557 htmlf("Expires: %s\n", http_date(item->st.st_mtime +
541 ttl_seconds(item->ttl))); 558 ttl_seconds(item->ttl)));
542 html("\n"); 559 html("\n");
543} 560}
544 561
545/* vim:set sw=8: */ 562/* vim:set sw=8: */