Index: src/descendants.c ================================================================== --- src/descendants.c +++ src/descendants.c @@ -329,11 +329,11 @@ "%s" " AND event.objid IN (SELECT rid FROM leaves)" " ORDER BY event.mtime DESC", timeline_query_for_tty() ); - print_timeline(&q, 20, 79, 0); + print_timeline(&q, -20, 79, 0); db_finalize(&q); } /* ** COMMAND: leaves* Index: src/search.c ================================================================== --- src/search.c +++ src/search.c @@ -189,12 +189,12 @@ int iBest; char fAll = NULL != find_option("all", "a", 0); /* If set, do not lop off the end of the results. */ char const * zLimit = find_option("limit","n",1); - int const nLimit = zLimit ? atoi(zLimit) : -1; /* Max number of entries - to list */ + int nLimit = zLimit ? atoi(zLimit) : -1000; /* Max number of matching + lines/entries to list */ db_must_be_within_tree(); if( g.argc<2 ) return; blob_init(&pattern, g.argv[2], -1); for(i=3; i%d ", iBest/3); } blob_append(&sql, "ORDER BY x DESC, date DESC ", -1); - if(nLimit>0){ - blob_appendf(&sql, "LIMIT %d", nLimit); - } db_prepare(&q, blob_str(&sql)); blob_reset(&sql); - print_timeline(&q, 1000, 79, 0); + print_timeline(&q, nLimit, 79, 0); db_finalize(&q); } Index: src/tag.c ================================================================== --- src/tag.c +++ src/tag.c @@ -389,11 +389,11 @@ int n; int fRaw = find_option("raw","",0)!=0; int fPropagate = find_option("propagate","",0)!=0; const char *zPrefix = fRaw ? "" : "sym-"; char const * zFindLimit = find_option("limit","n",1); - int const nFindLimit = zFindLimit ? atoi(zFindLimit) : 0; + int const nFindLimit = zFindLimit ? atoi(zFindLimit) : -2000; db_find_and_open_repository(0, 0); if( g.argc<3 ){ goto tag_cmd_usage; } @@ -467,16 +467,13 @@ " WHERE tagtype>0 AND tagid=%d" ")" " ORDER BY event.mtime DESC", timeline_query_for_tty(), zType, tagid ); - if( nFindLimit>0 ){ - blob_appendf(&sql, " LIMIT %d", nFindLimit); - } db_prepare(&q, "%s", blob_str(&sql)); blob_reset(&sql); - print_timeline(&q, 2000, 79, 0); + print_timeline(&q, nFindLimit, 79, 0); db_finalize(&q); } } }else Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -1494,14 +1494,17 @@ /* ** The input query q selects various records. Print a human-readable ** summary of those records. ** -** Limit the number of lines printed to mxLine. If mxLine is zero or -** negative there is no limit. The line limit is approximate because -** it is only checked on a per-entry basis. In verbose mode, the file -** name details are considered to be part of the entry. +** Limit number of lines or entries printed to nLimit. If nLimit is zero +** there is no limit. If nLimit is greater than zero, limit the number of +** complete entries printed. If nLimit is less than zero, attempt to limit +** the number of lines printed (this is basically the legacy behavior). +** The line limit, if used, is approximate because it is only checked on a +** per-entry basis. If verbose mode, the file name details are considered +** to be part of the entry. ** ** The query should return these columns: ** ** 0. rid ** 1. uuid @@ -1510,12 +1513,14 @@ ** 4. Number of non-merge children ** 5. Number of parents ** 6. mtime ** 7. branch */ -void print_timeline(Stmt *q, int mxLine, int width, int verboseFlag){ +void print_timeline(Stmt *q, int nLimit, int width, int verboseFlag){ + int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit; int nLine = 0; + int nEntry = 0; char zPrevDate[20]; const char *zCurrentUuid=0; int fchngQueryInit = 0; /* True if fchngQuery is initialized */ Stmt fchngQuery; /* Query for file changes on check-ins */ zPrevDate[0] = 0; @@ -1523,11 +1528,11 @@ if( g.localOpen ){ int rid = db_lget_int("checkout", 0); zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); } - while( db_step(q)==SQLITE_ROW && (mxLine<=0 || nLine<=mxLine) ){ + while( db_step(q)==SQLITE_ROW ){ int rid = db_column_int(q, 0); const char *zId = db_column_text(q, 1); const char *zDate = db_column_text(q, 2); const char *zCom = db_column_text(q, 3); int nChild = db_column_int(q, 4); @@ -1535,10 +1540,19 @@ char *zFree = 0; int n = 0; char zPrefix[80]; char zUuid[UUID_SIZE+1]; + if( nAbsLimit!=0 ){ + if( nLimit<0 && nLine>=nAbsLimit ){ + fossil_print("=== line limit (%d) reached ===\n", nAbsLimit); + break; /* line count limit hit, stop. */ + }else if( nEntry>=nAbsLimit ){ + fossil_print("=== entry limit (%d) reached ===\n", nAbsLimit); + break; /* entry count limit hit, stop. */ + } + } sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId); if( memcmp(zDate, zPrevDate, 10) ){ fossil_print("=== %.10s ===\n", zDate); memcpy(zPrevDate, zDate, 10); nLine++; /* record another line */ @@ -1596,10 +1610,11 @@ } nLine++; /* record another line */ } db_reset(&fchngQuery); } + nEntry++; /* record another complete entry */ } if( fchngQueryInit ) db_finalize(&fchngQuery); } /* @@ -1666,11 +1681,11 @@ ** The DATETIME should be in the ISO8601 format. For ** examples: "2007-08-18 07:21:21". You can also say "current" ** for the current version or "now" for the current time. ** ** Options: -** -n|--limit N Output the first N changes (default 20) +** -n|--limit N Output the first N entries (default 20 lines) ** -t|--type TYPE Output items from the given types only, such as: ** ci = file commits only ** e = events only ** t = tickets only ** w = wiki commits only @@ -1704,11 +1719,11 @@ zLimit = find_option("count",0,1); } if( zLimit ){ n = atoi(zLimit); }else{ - n = 20; + n = -20; } if( zWidth ){ width = atoi(zWidth); if( (width!=0) && (width<=20) ){ fossil_fatal("--width|-W value must be >20 or 0"); Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -188,11 +188,11 @@ "%s " " AND event.objid IN leaves" " ORDER BY event.mtime DESC", timeline_query_for_tty() ); - print_timeline(&q, 100, 79, 0); + print_timeline(&q, -100, 79, 0); db_finalize(&q); fossil_fatal("Multiple descendants"); } } tid = db_int(0, "SELECT rid FROM leaves, event"