/* ** Copyright (c) 2009 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** 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. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to implement the "finfo" command. */ #include "config.h" #include "finfo.h" /* ** COMMAND: finfo ** ** Usage: %fossil finfo FILENAME ** ** Print the change history for a single file. ** ** The "--limit N" and "--offset P" options limit the output to the first ** N changes after skipping P changes. ** ** The history of a file can also be viewed in the gui: ** * Go to the file browser and drill down to the file */ void finfo_cmd(void){ Stmt q; int vid; Blob dest; const char *zFilename; const char *zLimit; const char *zOffset; int iLimit, iOffset; db_must_be_within_tree(); vid = db_lget_int("checkout", 0); if( vid==0 ){ fossil_panic("no checkout to finfo files in"); } zLimit = find_option("limit",0,1); iLimit = zLimit ? atoi(zLimit) : -1; zOffset = find_option("offset",0,1); iOffset = zOffset ? atoi(zOffset) : 0; if (g.argc<3) { usage("FILENAME"); } file_tree_name(g.argv[2], &dest, 1); zFilename = blob_str(&dest); db_prepare(&q, "SELECT " " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* New file */ " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* The check-in */ " date(event.mtime,'localtime')," " coalesce(event.ecomment, event.comment)," " coalesce(event.euser, event.user)" " FROM mlink, event" " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" " AND event.objid=mlink.mid" " ORDER BY event.mtime DESC LIMIT %d OFFSET %d /*sort*/", zFilename, iLimit, iOffset ); printf("History of %s\n", zFilename); while( db_step(&q)==SQLITE_ROW ){ const char *zFileUuid = db_column_text(&q, 0); const char *zCiUuid = db_column_text(&q, 1); const char *zDate = db_column_text(&q, 2); const char *zCom = db_column_text(&q, 3); const char *zUser = db_column_text(&q, 4); char *zOut; printf("%s ", zDate); if( zFileUuid==0 ){ zOut = sqlite3_mprintf("[%.10s] DELETED %s (user: %s)", zCiUuid, zCom, zUser); }else{ zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", zCiUuid, zCom, zUser, zFileUuid); } comment_print(zOut, 11, 79); sqlite3_free(zOut); } db_finalize(&q); blob_reset(&dest); } /* ** WEBPAGE: finfo ** URL: /finfo?name=FILENAME ** ** Show the complete change history for a single file. */ void finfo_page(void){ Stmt q; const char *zFilename; char zPrevDate[20]; Blob title; GraphContext *pGraph; login_check_credentials(); if( !g.okRead ){ login_needed(); return; } style_header("File History"); login_anonymous_available(); zPrevDate[0] = 0; zFilename = PD("name",""); db_prepare(&q, "SELECT" " datetime(event.mtime,'localtime')," /* Date of change */ " coalesce(event.ecomment, event.comment)," /* Check-in comment */ " coalesce(event.euser, event.user)," /* User who made chng */ " mlink.pid," /* File rid */ " mlink.fid," /* Parent file rid */ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */ " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */ " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */ " event.bgcolor," /* Background color */ " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" " AND tagxref.rid=mlink.mid)" /* Tags */ " FROM mlink, event" " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" " AND event.objid=mlink.mid" " ORDER BY event.mtime DESC /*sort*/", TAG_BRANCH, zFilename ); blob_zero(&title); blob_appendf(&title, "History of "); hyperlinked_path(zFilename, &title); @
|
@ %s(zPrevDate)
@ | |||
| @ %s(zTime) | @if( zBgClr && zBgClr[0] ){ @ | }else{ @ | } sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); if( zUuid ){ if( g.okHistory ){ @ [%S(zUuid)] }else{ @ [%S(zUuid)] } @ part of check-in }else{ @ Deleted by check-in } hyperlink_to_uuid(zShortCkin); @ %h(zCom) (user: hyperlink_to_user(zUser, zDate, ""); @ branch: %h(zBr)) if( g.okHistory && zUuid ){ const char *z = zFilename; if( fpid ){ @ [diff] } @ @ [annotate] } @ |
| @ |