Index: src/add.c ================================================================== --- src/add.c +++ src/add.c @@ -78,11 +78,11 @@ static int numManifests; if( cachedManifest == -1 ){ int i; Blob repo; - cachedManifest = db_get_manifest_setting(); + cachedManifest = db_get_manifest_setting(0); numManifests = 0; for(i=0; izName, zName)==0 ){ - zVersionedSetting = fossil_strdup(cacheEntry->zValue); - break; - } - cacheEntry = cacheEntry->next; - } + if( zCkin==0 ){ + cacheEntry = cache; + while( cacheEntry!=0 ){ + if( fossil_strcmp(cacheEntry->zName, zName)==0 ){ + zVersionedSetting = fossil_strdup(cacheEntry->zValue); + break; + } + cacheEntry = cacheEntry->next; + } + } + /* Attempt to read value from file in check-out if there wasn't a cache hit.*/ if( cacheEntry==0 ){ Blob versionedPathname; Blob setting; - blob_zero(&versionedPathname); - blob_zero(&setting); - blob_appendf(&versionedPathname, "%s.fossil-settings/%s", - g.zLocalRoot, zName); - if( !g.localOpen ){ - /* Repository is in the process of being opened, but files have not been - * written to disk. Load from the database. */ - Blob noWarnFile; - if( historical_blob(g.zOpenRevision, blob_str(&versionedPathname), - &setting, 0) ){ - found = 1; - } - /* See if there's a no-warn flag */ - blob_append(&versionedPathname, ".no-warn", -1); - blob_zero(&noWarnFile); - if( historical_blob(g.zOpenRevision, blob_str(&versionedPathname), - &noWarnFile, 0) ){ - noWarn = 1; - } - blob_reset(&noWarnFile); - }else if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){ - /* File exists, and contains the value for this setting. Load from - ** the file. */ - const char *zFile = blob_str(&versionedPathname); - if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){ - found = 1; - } - /* See if there's a no-warn flag */ - blob_append(&versionedPathname, ".no-warn", -1); - if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){ - noWarn = 1; + blob_init(&versionedPathname, 0, 0); + blob_init(&setting, 0, 0); + if( !g.localOpen || zCkin!=0 ){ + /* Repository is in the process of being opened, but files have not been + * written to disk. Load from the database. */ + blob_appendf(&versionedPathname, ".fossil-settings/%s", zName); + if( historical_blob(zCkin ? zCkin : g.zOpenRevision, + blob_str(&versionedPathname), + &setting, 0) + ){ + found = 1; + } + }else{ + blob_appendf(&versionedPathname, "%s.fossil-settings/%s", + g.zLocalRoot, zName); + if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){ + /* File exists, and contains the value for this setting. Load from + ** the file. */ + const char *zFile = blob_str(&versionedPathname); + if( blob_read_from_file(&setting, zFile, ExtFILE)>=0 ){ + found = 1; + } + /* See if there's a no-warn flag */ + blob_append(&versionedPathname, ".no-warn", -1); + if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){ + noWarn = 1; + } } } blob_reset(&versionedPathname); if( found ){ blob_strip_comment_lines(&setting, &setting); @@ -3713,20 +3726,27 @@ blob_trim(&setting); /* Avoid non-obvious problems with line endings ** on boolean properties */ zVersionedSetting = fossil_strdup(blob_str(&setting)); } blob_reset(&setting); + /* Store result in cache, which can be the value or 0 if not found */ - cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(struct _cacheEntry)); - cacheEntry->next = cache; - cacheEntry->zName = zName; - cacheEntry->zValue = fossil_strdup(zVersionedSetting); - cache = cacheEntry; + if( zCkin==0 ){ + cacheEntry = (struct _cacheEntry*)fossil_malloc(sizeof(*cacheEntry)); + cacheEntry->next = cache; + cacheEntry->zName = zName; + cacheEntry->zValue = fossil_strdup(zVersionedSetting); + cache = cacheEntry; + } } + /* Display a warning? */ - if( zVersionedSetting!=0 && zNonVersionedSetting!=0 - && zNonVersionedSetting[0]!='\0' && !noWarn + if( zVersionedSetting!=0 + && zNonVersionedSetting!=0 + && zNonVersionedSetting[0]!='\0' + && zCkin==0 + && !noWarn ){ /* There's a versioned setting, and a non-versioned setting. Tell ** the user about the conflict */ fossil_warning( "setting %s has both versioned and non-versioned values: using " @@ -3735,10 +3755,11 @@ "\"%/.fossil-settings/%s.no-warn\" in the check-out root, or delete " "the non-versioned setting with \"fossil unset %s\")", zName, g.zLocalRoot, zName, g.zLocalRoot, zName, zName ); } + /* Prefer the versioned setting */ return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting; } @@ -3778,11 +3799,11 @@ } if( pSetting!=0 && pSetting->versionable ){ /* This is a versionable setting, try and get the info from a ** checked-out file */ char * zZ = z; - z = db_get_versioned(zName, z); + z = db_get_versioned(zName, z, 0); if(zZ != z){ fossil_free(zZ); } } if( z==0 ){ @@ -3919,11 +3940,11 @@ } fossil_free(zVal); return dflt; } int db_get_versioned_boolean(const char *zName, int dflt){ - char *zVal = db_get_versioned(zName, 0); + char *zVal = db_get_versioned(zName, 0, 0); if( zVal==0 ) return dflt; if( is_truth(zVal) ) return 1; if( is_false(zVal) ) return 0; return dflt; } @@ -4048,14 +4069,30 @@ ** Get the manifest setting. For backwards compatibility first check if the ** value is a boolean. If it's not a boolean, treat each character as a flag ** to enable a manifest type. This system puts certain boundary conditions on ** which letters can be used to represent flags (any permutation of flags must ** not be able to fully form one of the boolean values). +** +** "manifest" is a versionable setting. But we do not issue a warning +** if there is a conflict. Instead, the value returned is the value for +** the versioned setting if the versioned setting exists, or the ordinary +** setting otherwise. +** +** The argument zCkin is the specific check-in for which we want the +** manifest setting. */ -int db_get_manifest_setting(void){ +int db_get_manifest_setting(const char *zCkin){ int flg; - char *zVal = db_get("manifest", 0); + char *zVal; + + /* Look for the versioned setting first */ + zVal = db_get_versioned("manifest", 0, zCkin); + + if( zVal==0 && g.repositoryOpen ){ + /* No versioned setting, look for the repository setting second */ + zVal = db_text(0, "SELECT value FROM config WHERE name='manifest'"); + } if( zVal==0 || is_false(zVal) ){ return 0; }else if( is_truth(zVal) ){ return MFESTFLG_RAW|MFESTFLG_UUID; } @@ -4068,10 +4105,37 @@ } zVal++; } return flg; } + +/* +** COMMAND: test-manifest-setting +** +** Usage: %fossil test-manifest-setting VERSION VERSION ... +** +** Display the value for the "manifest" setting for various versions +** of the repository. +*/ +void test_manfest_setting_cmd(void){ + int i; + db_find_and_open_repository(0, 0); + for(i=2; iname, NULL)); + fossil_print("%s\n", db_get_versioned(pSetting->name, NULL, NULL)); return; } if( g.repositoryOpen ){ db_prepare(&q, "SELECT '(local)', value FROM config WHERE name=%Q" Index: src/export.c ================================================================== --- src/export.c +++ src/export.c @@ -1074,12 +1074,11 @@ */ static int gitmirror_send_checkin( FILE *xCmd, /* Write fast-import text on this pipe */ int rid, /* BLOB.RID for the check-in to export */ const char *zUuid, /* BLOB.UUID for the check-in to export */ - int *pnLimit, /* Stop when the counter reaches zero */ - int fManifest /* MFESTFLG_* values */ + int *pnLimit /* Stop when the counter reaches zero */ ){ Manifest *pMan; /* The check-in to be output */ int i; /* Loop counter */ int iParent; /* Which immediate ancestor is primary. -1 for none */ Stmt q; /* An SQL query */ @@ -1089,10 +1088,12 @@ Blob comment; /* The comment text for the check-in */ int nErr = 0; /* Number of errors */ int bPhantomOk; /* True if phantom files should be ignored */ char buf[24]; char *zEmail; /* Contact info for Git committer field */ + int fManifest; /* Should the manifest files be included? */ + int fPManifest = 0; /* OR of the manifest files for all parents */ pMan = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pMan==0 ){ /* Must be a phantom. Return without doing anything, and in particular ** without creating a mark for this check-in. */ @@ -1106,11 +1107,11 @@ char *zPMark = gitmirror_find_mark(pMan->azParent[i], 0, 0); if( zPMark==0 ){ int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pMan->azParent[i]); int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i], - pnLimit, fManifest); + pnLimit); if( rc || *pnLimit<=0 ){ manifest_destroy(pMan); return 1; } } @@ -1215,10 +1216,11 @@ blob_reset(&comment); iParent = -1; /* Which ancestor is the primary parent */ for(i=0; inParent; i++){ char *zOther = gitmirror_find_mark(pMan->azParent[i],0,0); if( zOther==0 ) continue; + fPManifest |= db_get_manifest_setting(pMan->azParent[i]); if( iParent<0 ){ iParent = i; fprintf(xCmd, "from %s\n", zOther); }else{ fprintf(xCmd, "merge %s\n", zOther); @@ -1271,29 +1273,36 @@ db_finalize(&q); manifest_destroy(pMan); pMan = 0; /* Include Fossil-generated auxiliary files in the check-in */ + fManifest = db_get_manifest_setting(zUuid); if( fManifest & MFESTFLG_RAW ){ Blob manifest; content_get(rid, &manifest); sterilize_manifest(&manifest, CFTYPE_MANIFEST); fprintf(xCmd,"M 100644 inline manifest\ndata %d\n%s\n", blob_strlen(&manifest), blob_str(&manifest)); blob_reset(&manifest); + }else if( fPManifest & MFESTFLG_RAW ){ + fprintf(xCmd, "D manifest\n"); } if( fManifest & MFESTFLG_UUID ){ int n = (int)strlen(zUuid); fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n\n", n+1, zUuid); + }else if( fPManifest & MFESTFLG_UUID ){ + fprintf(xCmd, "D manifest.uuid\n"); } if( fManifest & MFESTFLG_TAGS ){ Blob tagslist; blob_init(&tagslist, 0, 0); get_checkin_taglist(rid, &tagslist); fprintf(xCmd,"M 100644 inline manifest.tags\ndata %d\n%s\n", blob_strlen(&tagslist), blob_str(&tagslist)); blob_reset(&tagslist); + }else if( fPManifest & MFESTFLG_TAGS ){ + fprintf(xCmd, "D manifest.tags\n"); } /* The check-in is finished, so decrement the counter */ (*pnLimit)--; return 0; @@ -1383,11 +1392,10 @@ char *zPushUrl; /* URL to sync the mirror to */ double rEnd; /* time of most recent export */ int rc; /* Result code */ int bForce; /* Do the export and sync even if no changes*/ int bNeedRepack = 0; /* True if we should run repack at the end */ - int fManifest; /* Current "manifest" setting */ int bIfExists; /* The --if-mirrored flag */ FILE *xCmd; /* Pipe to the "git fast-import" command */ FILE *pMarks; /* Git mark files */ Stmt q; /* Queries */ char zLine[200]; /* One line of a mark file */ @@ -1521,13 +1529,10 @@ gitmirror_message(VERB_NORMAL, "no changes\n"); db_commit_transaction(); return; } - /* Do we need to include manifest files in the clone? */ - fManifest = db_get_manifest_setting(); - /* Change to the MIRROR directory so that the Git commands will work */ rc = file_chdir(zMirror, 0); if( rc ) fossil_fatal("cannot change the working directory to \"%s\"", zMirror); @@ -1579,11 +1584,11 @@ while( nLimit && db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); double rMTime = db_column_double(&q, 1); const char *zUuid = db_column_text(&q, 2); if( rMTime>rEnd ) rEnd = rMTime; - rc = gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest); + rc = gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit); if( rc ) break; gitmirror_message(VERB_NORMAL,"%d/%d \r", nTotal-nLimit, nTotal); fflush(stdout); } db_finalize(&q); Index: src/setup.c ================================================================== --- src/setup.c +++ src/setup.c @@ -1157,11 +1157,11 @@ @
login_insert_csrf_secret(); for(i=0, pSet=aSetting; iwidth==0 ){ int hasVersionableValue = pSet->versionable && - (db_get_versioned(pSet->name, NULL)!=0); + (db_get_versioned(pSet->name, NULL, NULL)!=0); onoff_attribute("", pSet->name, pSet->var!=0 ? pSet->var : pSet->name /*works-like:"x"*/, is_truth(pSet->def), hasVersionableValue); @ %h(pSet->name) if( pSet->versionable ){ @@ -1175,11 +1175,11 @@ @ @ for(i=0, pSet=aSetting; iwidth>0 && !pSet->forceTextArea ){ int hasVersionableValue = pSet->versionable && - (db_get_versioned(pSet->name, NULL)!=0); + (db_get_versioned(pSet->name, NULL, NULL)!=0); @
@ %h(pSet->name) if( pSet->versionable ){ @ (v) } else { @@ -1194,11 +1194,11 @@ } @
@
for(i=0, pSet=aSetting; iwidth>0 && pSet->forceTextArea ){ - int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0; + int hasVersionableValue = db_get_versioned(pSet->name, NULL, NULL)!=0; @ %s(pSet->name) if( pSet->versionable ){ @ (v)
} else { @
Index: src/tar.c ================================================================== --- src/tar.c +++ src/tar.c @@ -499,11 +499,11 @@ pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ int flg, eflg = 0; mTime = (unsigned)((pManifest->rDate - 2440587.5)*86400.0); if( pTar ) tar_begin(mTime); - flg = db_get_manifest_setting(); + flg = db_get_manifest_setting(blob_str(&hash)); if( flg ){ /* eflg is the effective flags, taking include/exclude into account */ if( (pInclude==0 || glob_match(pInclude, "manifest")) && !glob_match(pExclude, "manifest") && (flg & MFESTFLG_RAW) ){ Index: src/zip.c ================================================================== --- src/zip.c +++ src/zip.c @@ -652,11 +652,11 @@ pManifest = manifest_get(rid, CFTYPE_MANIFEST, 0); if( pManifest ){ int flg, eflg = 0; char *zName = 0; zip_set_timedate(pManifest->rDate); - flg = db_get_manifest_setting(); + flg = db_get_manifest_setting(blob_str(&hash)); if( flg ){ /* eflg is the effective flags, taking include/exclude into account */ if( (pInclude==0 || glob_match(pInclude, "manifest")) && !glob_match(pExclude, "manifest") && (flg & MFESTFLG_RAW) ){