Fossil SCM

Corrected propagation of deleted-via-delta F-cards. Added option to save generated manifest (on success) to a file. General cleanups.

stephan 2020-04-30 17:55 UTC checkin-without-checkout
Commit fcdd76f6fbcf2eab6d0716be197e37b3d9fab9e37962d57705c9aef5b13051bc
1 file changed +138 -93
+138 -93
--- src/checkin.c
+++ src/checkin.c
@@ -2697,72 +2697,49 @@
26972697
}
26982698
}
26992699
27002700
/*
27012701
** State for the "mini-checkin" infrastructure, which enables the
2702
-** ability to commit changes to a single file via an HTTP request.
2702
+** ability to commit changes to a single file without a checkout
2703
+** db, e.g. for use via an HTTP request.
27032704
**
27042705
** Memory for all non-const (char *) members is owned by the
2705
-** CheckinMiniInfo instance.
2706
+** CheckinMiniInfo instance and is freed by CheckinMiniInfo_cleanup().
27062707
*/
27072708
struct CheckinMiniInfo {
2708
- Manifest * pParent; /* parent checkin */
2709
+ Manifest * pParent; /* parent checkin. Memory is owned by this
2710
+ object. */
27092711
char *zParentUuid; /* UUID of pParent */
2710
- Blob comment; /* Check-in comment text */
2711
- char *zMimetype; /* Mimetype of check-in command. May be NULL */
2712
- char *zUser; /* User name */
2713
- char *zDate; /* Optionally force this date string (anything
2714
- supported by date_in_standard_format()).
2715
- Maybe be NULL. */
27162712
char *zFilename; /* Name of single file to commit. Must be
27172713
relative to the top of the repo. */
27182714
Blob fileContent; /* Content of file referred to by zFilename. */
27192715
Blob fileHash; /* Hash of this->fileContent, using the repo's
27202716
preferred hash method. */
2721
- int filePerm; /* Permissions (via file_perm()) of file. We
2722
- need to store this before calling
2717
+ Blob comment; /* Check-in comment text */
2718
+ char *zMimetype; /* Mimetype of comment. May be NULL */
2719
+ char *zUser; /* User name */
2720
+ char *zDate; /* Optionally force this date string (anything
2721
+ supported by date_in_standard_format()).
2722
+ Maybe be NULL. */
2723
+ Blob *pMfOut; /* If not NULL, checkin_mini() will write a
2724
+ copy of the generated manifest here. This
2725
+ memory is NOT owned by CheckinMiniInfo. */
2726
+ int filePerm; /* Permissions (via file_perm()) of the input
2727
+ file. We need to store this before calling
27232728
checkin_mini() because the real input file
2724
- name may differ from this->zFilename and
2725
- checkin_mini() requires the permissions of
2726
- the original file. For web commits, set this
2727
- to PERM_REG before calling
2728
- checkin_mini(). */
2729
- int flags; /* Bitmask of fossil_cimini_flags for
2730
- communication from checkin_mini() to
2731
- create_manifest_mini(). */
2729
+ name may differ from the repo-centric
2730
+ this->zFilename, and checkin_mini() requires
2731
+ the permissions of the original file. For
2732
+ web commits, set this to PERM_REG or (when
2733
+ editing executable scripts) PERM_EXE before
2734
+ calling checkin_mini(). */
2735
+ int flags; /* Bitmask of fossil_cimini_flags. */
27322736
};
27332737
typedef struct CheckinMiniInfo CheckinMiniInfo;
2734
-/*
2735
-** Initializes p to a known-valid default state.
2736
-*/
2737
-static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
2738
- memset(p, 0, sizeof(CheckinMiniInfo));
2739
- p->flags = 0;
2740
- p->filePerm = -1;
2741
- p->comment = p->fileContent = p->fileHash = empty_blob;
2742
-}
2743
-
2744
-/*
2745
-** Frees all memory owned by p, but does not free p.
2746
- */
2747
-static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
2748
- blob_reset(&p->comment);
2749
- blob_reset(&p->fileContent);
2750
- blob_reset(&p->fileHash);
2751
- if(p->pParent){
2752
- manifest_destroy(p->pParent);
2753
- }
2754
- fossil_free(p->zFilename);
2755
- fossil_free(p->zMimetype);
2756
- fossil_free(p->zParentUuid);
2757
- fossil_free(p->zUser);
2758
- fossil_free(p->zDate);
2759
- CheckinMiniInfo_init(p);
2760
-}
2761
-
2762
-/*
2763
-** Flags for checkin_mini()
2738
+
2739
+/*
2740
+** CheckinMiniInfo::flags values.
27642741
*/
27652742
enum fossil_cimini_flags {
27662743
CIMINI_NONE = 0,
27672744
/*
27682745
** Tells checkin_mini() to use dry-run mode.
@@ -2824,10 +2801,38 @@
28242801
** the inadvertent addition of a new file when an update to an
28252802
** existing was intended, as a side-effect of name-case differences.
28262803
*/
28272804
CIMINI_ALLOW_NEW_FILE = 1<<8
28282805
};
2806
+
2807
+/*
2808
+** Initializes p to a known-valid default state.
2809
+*/
2810
+static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
2811
+ memset(p, 0, sizeof(CheckinMiniInfo));
2812
+ p->flags = CIMINI_NONE;
2813
+ p->filePerm = -1;
2814
+ p->comment = p->fileContent = p->fileHash = empty_blob;
2815
+}
2816
+
2817
+/*
2818
+** Frees all memory owned by p, but does not free p.
2819
+ */
2820
+static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
2821
+ blob_reset(&p->comment);
2822
+ blob_reset(&p->fileContent);
2823
+ blob_reset(&p->fileHash);
2824
+ if(p->pParent){
2825
+ manifest_destroy(p->pParent);
2826
+ }
2827
+ fossil_free(p->zFilename);
2828
+ fossil_free(p->zMimetype);
2829
+ fossil_free(p->zParentUuid);
2830
+ fossil_free(p->zUser);
2831
+ fossil_free(p->zDate);
2832
+ CheckinMiniInfo_init(p);
2833
+}
28292834
28302835
/*
28312836
** Internal helper which returns an F-card perms string suitable for
28322837
** writing into a manifest.
28332838
*/
@@ -2840,10 +2845,31 @@
28402845
}
28412846
28422847
static const char * mfile_perm_mstring(const ManifestFile * p){
28432848
return mfile_permint_mstring(manifest_file_mperm(p));
28442849
}
2850
+
2851
+/*
2852
+** Internal helper for checkin_mini() and friends. Appends an F-card
2853
+** for p to pOut.
2854
+*/
2855
+static void checkin_mini_append_fcard(Blob *pOut, const ManifestFile *p){
2856
+ if(p->zUuid){
2857
+ assert(*p->zUuid);
2858
+ blob_appendf(pOut, "F %F %s%s", p->zName,
2859
+ p->zUuid, mfile_perm_mstring(p));
2860
+ if(p->zPrior){
2861
+ assert(*p->zPrior);
2862
+ blob_appendf(pOut, " %F\n", p->zPrior);
2863
+ }else{
2864
+ blob_append(pOut, "\n", 1);
2865
+ }
2866
+ }else{
2867
+ /* File was removed from parent delta. */
2868
+ blob_appendf(pOut, "F %F\n", p->zName);
2869
+ }
2870
+}
28452871
28462872
/*
28472873
** Handles the F-card parts for create_manifest_mini().
28482874
**
28492875
** If asDelta is true, F-cards will be handled as for a delta
@@ -2855,11 +2881,11 @@
28552881
*/
28562882
static int create_manifest_mini_fcards( Blob * pOut,
28572883
CheckinMiniInfo * pCI,
28582884
int asDelta,
28592885
Blob * pErr){
2860
- ManifestFile *zFile; /* One file entry from pCI->pParent */
2886
+ ManifestFile *pFile; /* One file entry from pCI->pParent */
28612887
const char *zFilename = 0; /* filename for new F-card */
28622888
const char *zUuid = 0; /* UUID for new F-card */
28632889
int cmp = 0; /* filename comparison result */
28642890
int iFCursor = 0; /* Cursor into pCI->pParent->aFile if
28652891
pCI->pParent is a delta. */
@@ -2882,18 +2908,18 @@
28822908
if(asDelta){
28832909
if(pCI->pParent->zBaseline==0 || pCI->pParent->nFile==0 ){
28842910
/* Parent is a baseline or a delta with no F-cards, so this is
28852911
** the simplest case: create a delta with a single F-card.
28862912
*/
2887
- zFile = manifest_file_find(pCI->pParent, pCI->zFilename);
2888
- if(zFile==0){/* New file */
2913
+ pFile = manifest_file_find(pCI->pParent, pCI->zFilename);
2914
+ if(pFile==0){/* New file */
28892915
zFilename = pCI->zFilename;
28902916
}else{/* Replacement file */
2891
- if(manifest_file_mperm(zFile)==PERM_LNK){
2917
+ if(manifest_file_mperm(pFile)==PERM_LNK){
28922918
goto err_no_symlink;
28932919
}
2894
- zFilename = zFile->zName
2920
+ zFilename = pFile->zName
28952921
/* use original name in case of name-case difference */;
28962922
}
28972923
postProcess = 0;
28982924
}else{
28992925
/* Parent is a delta manifest with F-cards. Traversal of delta
@@ -2907,57 +2933,51 @@
29072933
*/
29082934
Manifest * p = pCI->pParent;
29092935
cmp = -1;
29102936
assert(p->nFile > 0);
29112937
iFCursor = 0;
2912
- zFile = &p->aFile[iFCursor];
2938
+ pFile = &p->aFile[iFCursor];
29132939
/* Write F-cards which lexically preceed pCI->zFilename */
29142940
for( ; iFCursor<p->nFile; ){
2915
- zFile = &p->aFile[iFCursor];
2916
- cmp = fncmp(zFile->zName, pCI->zFilename);
2941
+ pFile = &p->aFile[iFCursor];
2942
+ cmp = fncmp(pFile->zName, pCI->zFilename);
29172943
if(cmp<0){
29182944
++iFCursor;
2919
- if(zFile->zUuid){
2920
- blob_appendf(pOut, "F %F %s%s\n", zFile->zName,
2921
- zFile->zUuid, mfile_perm_mstring(zFile));
2922
- }else{/* File was removed in parent delta */
2923
- blob_appendf(pOut, "F %F\n", zFile->zName);
2924
- }
2945
+ checkin_mini_append_fcard(pOut,pFile);
29252946
}else{
29262947
break;
29272948
}
29282949
}
29292950
if(0==cmp){/* Match: override this F-card */
2930
- assert(zFile);
2931
- if(manifest_file_mperm(zFile)==PERM_LNK){
2951
+ assert(pFile);
2952
+ if(manifest_file_mperm(pFile)==PERM_LNK){
29322953
goto err_no_symlink;
29332954
}
29342955
++iFCursor;
2935
- zFilename = zFile->zName
2956
+ zFilename = pFile->zName
29362957
/* use original name in case of name-case difference */;
29372958
}else{/* This is a new file */
29382959
zFilename = pCI->zFilename;
29392960
}
29402961
postProcess = 2;
29412962
}
29422963
}else{/* Non-delta: write F-cards which lexically preceed
29432964
pCI->zFilename */
29442965
cmp = -1;
2945
- while((zFile = manifest_file_next(pCI->pParent, 0))
2946
- && (cmp = fncmp(zFile->zName, pCI->zFilename))<0){
2947
- blob_appendf(pOut, "F %F %s%s\n", zFile->zName, zFile->zUuid,
2948
- mfile_perm_mstring(zFile));
2966
+ while((pFile = manifest_file_next(pCI->pParent, 0))
2967
+ && (cmp = fncmp(pFile->zName, pCI->zFilename))<0){
2968
+ checkin_mini_append_fcard(pOut,pFile);
29492969
}
29502970
if(cmp==0){/* Match: override this F-card*/
2951
- if(manifest_file_mperm(zFile)==PERM_LNK){
2971
+ if(manifest_file_mperm(pFile)==PERM_LNK){
29522972
goto err_no_symlink;
29532973
}
2954
- zFilename = zFile->zName
2974
+ zFilename = pFile->zName
29552975
/* use original name in case of name-case difference */;
29562976
}else{/* This is a new file. */
29572977
zFilename = pCI->zFilename;
2958
- if(zFile!=0){
2978
+ if(pFile!=0){
29592979
assert(cmp>0);
29602980
assert(pCI->pParent->iFile>0);
29612981
--pCI->pParent->iFile
29622982
/* So that the post-processing loop picks up this file
29632983
again.*/;
@@ -2964,44 +2984,38 @@
29642984
}
29652985
}
29662986
postProcess = 1;
29672987
}
29682988
/* Finally add the new file's F-card... */
2969
- zFile = 0;
2989
+ pFile = 0;
29702990
zUuid = blob_str(&pCI->fileHash);
29712991
assert(zFilename);
29722992
assert(zUuid);
29732993
assert(postProcess==0 || postProcess==1 || postProcess==2);
29742994
blob_appendf(pOut, "F %F %s%s\n", zFilename, zUuid,
29752995
mfile_permint_mstring(pCI->filePerm));
29762996
while(postProcess>0){
29772997
/* Write F-cards which lexically follow pCI->zFilename */
29782998
if(postProcess==1){ /* non-delta parent */
2979
- zFile = manifest_file_next(pCI->pParent, 0);
2999
+ pFile = manifest_file_next(pCI->pParent, 0);
29803000
}else{ /* clone directly from delta parent */
2981
- zFile = iFCursor<pCI->pParent->nFile
3001
+ pFile = iFCursor<pCI->pParent->nFile
29823002
? &pCI->pParent->aFile[iFCursor++] : 0;
29833003
}
2984
- if(zFile==0){
3004
+ if(pFile==0){
29853005
break;
29863006
}
29873007
#ifndef NDEBUG
2988
- cmp = fncmp(zFile->zName, pCI->zFilename);
3008
+ cmp = fncmp(pFile->zName, pCI->zFilename);
29893009
assert(cmp>0);
29903010
if(cmp<=0){
29913011
mf_err((pErr,"Internal error: mis-ordering of "
29923012
"F-cards detected."));
29933013
}
29943014
#endif
2995
- if(zFile->zUuid){
2996
- blob_appendf(pOut, "F %F %s%s\n", zFile->zName, zFile->zUuid,
2997
- mfile_perm_mstring(zFile));
2998
- }else{
2999
- assert(postProcess==2);
3000
- /* File was removed from parent delta. */
3001
- blob_appendf(pOut, "F %F\n", zFile->zName);
3002
- }
3015
+ assert(pFile->zUuid || 2==postProcess);
3016
+ checkin_mini_append_fcard(pOut,pFile);
30033017
}
30043018
return 1;
30053019
err_no_symlink:
30063020
mf_err((pErr,"Cannot commit or overwrite symlinks "
30073021
"via mini-checkin."));
@@ -3316,14 +3330,20 @@
33163330
if(create_manifest_mini(&mf, pCI, pErr)==0){
33173331
return 0;
33183332
}
33193333
isPrivate = content_is_private(pCI->pParent->rid);
33203334
rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
3321
- content_deltify(rid, &pCI->pParent->rid, 1, 0);
33223335
if(pCI->flags & CIMINI_DUMP_MANIFEST){
3323
- fossil_print("Manifest %z:\n%b", rid_to_uuid(rid), &mf);
3336
+ fossil_print("%b", &mf);
3337
+ }
3338
+ if(pCI->pMfOut!=0){
3339
+ /* Cross-linking clears mf, so we have to copy it,
3340
+ ** instead of taking over its memory. */
3341
+ blob_reset(pCI->pMfOut);
3342
+ blob_append(pCI->pMfOut, blob_buffer(&mf), blob_size(&mf));
33243343
}
3344
+ content_deltify(rid, &pCI->pParent->rid, 1, 0);
33253345
manifest_crosslink(rid, &mf, 0);
33263346
blob_reset(&mf);
33273347
/* Save and deltify the file content... */
33283348
frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
33293349
0, 0, isPrivate);
@@ -3388,11 +3408,14 @@
33883408
** --allow-new-file Allow addition of a new file this way.
33893409
** Disabled by default to avoid that case-
33903410
** sensitivity errors inadvertently lead to
33913411
** adding a new file where an update is
33923412
** intended.
3393
-** --dump-manifest|-d Dumps the generated manifest to stdout.
3413
+** --dump-manifest|-d Dumps the generated manifest to stdout
3414
+** immediately after it's generated.
3415
+** --save-manifest FILE Saves the generated manifest to a file
3416
+** after successfully processing it.
33943417
** --wet-run Disables the default dry-run mode.
33953418
**
33963419
** Example:
33973420
**
33983421
** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c
@@ -3406,10 +3429,11 @@
34063429
const char * zCommentFile; /* -M FILE */
34073430
const char * zAsFilename; /* --as filename */
34083431
const char * zRevision; /* --revision|-r [=trunk|checkout] */
34093432
const char * zUser; /* --user-override */
34103433
const char * zDate; /* --date-override */
3434
+ char const * zManifestFile = 0;/* --save-manifest FILE */
34113435
34123436
/* This function should perform only the minimal "business logic" it
34133437
** needs in order to fully/properly populate the CheckinMiniInfo and
34143438
** then pass it on to checkin_mini() to do most of the validation
34153439
** and work. The point of this is to avoid duplicate code when a web
@@ -3420,10 +3444,11 @@
34203444
zCommentFile = find_option("comment-file","M",1);
34213445
zAsFilename = find_option("as",0,1);
34223446
zRevision = find_option("revision","r",1);
34233447
zUser = find_option("user-override",0,1);
34243448
zDate = find_option("date-override",0,1);
3449
+ zManifestFile = find_option("save-manifest",0,1);
34253450
if(find_option("wet-run",0,0)==0){
34263451
cinf.flags |= CIMINI_DRY_RUN;
34273452
}
34283453
if(find_option("allow-fork",0,0)!=0){
34293454
cinf.flags |= CIMINI_ALLOW_FORK;
@@ -3466,10 +3491,11 @@
34663491
}
34673492
if(!blob_size(&cinf.comment)){
34683493
fossil_fatal("Non-empty checkin comment is required.");
34693494
}
34703495
}
3496
+ db_begin_transaction();
34713497
zFilename = g.argv[2];
34723498
cinf.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename);
34733499
cinf.filePerm = file_perm(zFilename, ExtFILE);
34743500
cinf.zUser = mprintf("%s", zUser ? zUser : login_name());
34753501
if(zDate){
@@ -3484,24 +3510,43 @@
34843510
}
34853511
name_to_uuid2(zRevision, "ci", &cinf.zParentUuid);
34863512
if(cinf.zParentUuid==0){
34873513
fossil_fatal("Cannot determine version to commit to.");
34883514
}
3489
- blob_read_from_file(&cinf.fileContent, zFilename,
3490
- ExtFILE/*may want to reconsider*/);
3515
+ blob_read_from_file(&cinf.fileContent, zFilename, ExtFILE);
34913516
{
3517
+ Blob theManifest = empty_blob; /* --save-manifest target */
34923518
Blob errMsg = empty_blob;
3493
- const int rc = checkin_mini(&cinf, &newRid, &errMsg);
3494
- CheckinMiniInfo_cleanup(&cinf);
3519
+ int rc;
3520
+ if(zManifestFile){
3521
+ cinf.pMfOut = &theManifest;
3522
+ }
3523
+ rc = checkin_mini(&cinf, &newRid, &errMsg);
34953524
if(rc){
34963525
assert(blob_size(&errMsg)==0);
34973526
}else{
34983527
assert(blob_size(&errMsg));
34993528
fossil_fatal("%b", &errMsg);
35003529
}
3530
+ if(zManifestFile){
3531
+ fossil_print("Writing manifest to: %s\n", zManifestFile);
3532
+ assert(blob_size(&theManifest)>0);
3533
+ blob_write_to_file(&theManifest, zManifestFile);
3534
+ blob_reset(&theManifest);
3535
+ }
3536
+ }
3537
+ if(newRid!=0){
3538
+ fossil_print("New version%s: %z\n",
3539
+ (cinf.flags & CIMINI_DRY_RUN) ? " (dry run)" : "",
3540
+ rid_to_uuid(newRid));
35013541
}
3542
+ db_end_transaction(0/*checkin_mini() will have triggered it to roll
3543
+ ** back in dry-run mode, but we need access to
3544
+ ** the transaction-written db state in this
3545
+ ** routine.*/);
35023546
if(!(cinf.flags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){
35033547
fossil_warning("The checkout state is now out of sync "
35043548
"with regards to this commit. It needs to be "
35053549
"'update'd or 'close'd and re-'open'ed.");
35063550
}
3551
+ CheckinMiniInfo_cleanup(&cinf);
35073552
}
35083553
--- src/checkin.c
+++ src/checkin.c
@@ -2697,72 +2697,49 @@
2697 }
2698 }
2699
2700 /*
2701 ** State for the "mini-checkin" infrastructure, which enables the
2702 ** ability to commit changes to a single file via an HTTP request.
 
2703 **
2704 ** Memory for all non-const (char *) members is owned by the
2705 ** CheckinMiniInfo instance.
2706 */
2707 struct CheckinMiniInfo {
2708 Manifest * pParent; /* parent checkin */
 
2709 char *zParentUuid; /* UUID of pParent */
2710 Blob comment; /* Check-in comment text */
2711 char *zMimetype; /* Mimetype of check-in command. May be NULL */
2712 char *zUser; /* User name */
2713 char *zDate; /* Optionally force this date string (anything
2714 supported by date_in_standard_format()).
2715 Maybe be NULL. */
2716 char *zFilename; /* Name of single file to commit. Must be
2717 relative to the top of the repo. */
2718 Blob fileContent; /* Content of file referred to by zFilename. */
2719 Blob fileHash; /* Hash of this->fileContent, using the repo's
2720 preferred hash method. */
2721 int filePerm; /* Permissions (via file_perm()) of file. We
2722 need to store this before calling
 
 
 
 
 
 
 
 
 
2723 checkin_mini() because the real input file
2724 name may differ from this->zFilename and
2725 checkin_mini() requires the permissions of
2726 the original file. For web commits, set this
2727 to PERM_REG before calling
2728 checkin_mini(). */
2729 int flags; /* Bitmask of fossil_cimini_flags for
2730 communication from checkin_mini() to
2731 create_manifest_mini(). */
2732 };
2733 typedef struct CheckinMiniInfo CheckinMiniInfo;
2734 /*
2735 ** Initializes p to a known-valid default state.
2736 */
2737 static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
2738 memset(p, 0, sizeof(CheckinMiniInfo));
2739 p->flags = 0;
2740 p->filePerm = -1;
2741 p->comment = p->fileContent = p->fileHash = empty_blob;
2742 }
2743
2744 /*
2745 ** Frees all memory owned by p, but does not free p.
2746 */
2747 static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
2748 blob_reset(&p->comment);
2749 blob_reset(&p->fileContent);
2750 blob_reset(&p->fileHash);
2751 if(p->pParent){
2752 manifest_destroy(p->pParent);
2753 }
2754 fossil_free(p->zFilename);
2755 fossil_free(p->zMimetype);
2756 fossil_free(p->zParentUuid);
2757 fossil_free(p->zUser);
2758 fossil_free(p->zDate);
2759 CheckinMiniInfo_init(p);
2760 }
2761
2762 /*
2763 ** Flags for checkin_mini()
2764 */
2765 enum fossil_cimini_flags {
2766 CIMINI_NONE = 0,
2767 /*
2768 ** Tells checkin_mini() to use dry-run mode.
@@ -2824,10 +2801,38 @@
2824 ** the inadvertent addition of a new file when an update to an
2825 ** existing was intended, as a side-effect of name-case differences.
2826 */
2827 CIMINI_ALLOW_NEW_FILE = 1<<8
2828 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2829
2830 /*
2831 ** Internal helper which returns an F-card perms string suitable for
2832 ** writing into a manifest.
2833 */
@@ -2840,10 +2845,31 @@
2840 }
2841
2842 static const char * mfile_perm_mstring(const ManifestFile * p){
2843 return mfile_permint_mstring(manifest_file_mperm(p));
2844 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2845
2846 /*
2847 ** Handles the F-card parts for create_manifest_mini().
2848 **
2849 ** If asDelta is true, F-cards will be handled as for a delta
@@ -2855,11 +2881,11 @@
2855 */
2856 static int create_manifest_mini_fcards( Blob * pOut,
2857 CheckinMiniInfo * pCI,
2858 int asDelta,
2859 Blob * pErr){
2860 ManifestFile *zFile; /* One file entry from pCI->pParent */
2861 const char *zFilename = 0; /* filename for new F-card */
2862 const char *zUuid = 0; /* UUID for new F-card */
2863 int cmp = 0; /* filename comparison result */
2864 int iFCursor = 0; /* Cursor into pCI->pParent->aFile if
2865 pCI->pParent is a delta. */
@@ -2882,18 +2908,18 @@
2882 if(asDelta){
2883 if(pCI->pParent->zBaseline==0 || pCI->pParent->nFile==0 ){
2884 /* Parent is a baseline or a delta with no F-cards, so this is
2885 ** the simplest case: create a delta with a single F-card.
2886 */
2887 zFile = manifest_file_find(pCI->pParent, pCI->zFilename);
2888 if(zFile==0){/* New file */
2889 zFilename = pCI->zFilename;
2890 }else{/* Replacement file */
2891 if(manifest_file_mperm(zFile)==PERM_LNK){
2892 goto err_no_symlink;
2893 }
2894 zFilename = zFile->zName
2895 /* use original name in case of name-case difference */;
2896 }
2897 postProcess = 0;
2898 }else{
2899 /* Parent is a delta manifest with F-cards. Traversal of delta
@@ -2907,57 +2933,51 @@
2907 */
2908 Manifest * p = pCI->pParent;
2909 cmp = -1;
2910 assert(p->nFile > 0);
2911 iFCursor = 0;
2912 zFile = &p->aFile[iFCursor];
2913 /* Write F-cards which lexically preceed pCI->zFilename */
2914 for( ; iFCursor<p->nFile; ){
2915 zFile = &p->aFile[iFCursor];
2916 cmp = fncmp(zFile->zName, pCI->zFilename);
2917 if(cmp<0){
2918 ++iFCursor;
2919 if(zFile->zUuid){
2920 blob_appendf(pOut, "F %F %s%s\n", zFile->zName,
2921 zFile->zUuid, mfile_perm_mstring(zFile));
2922 }else{/* File was removed in parent delta */
2923 blob_appendf(pOut, "F %F\n", zFile->zName);
2924 }
2925 }else{
2926 break;
2927 }
2928 }
2929 if(0==cmp){/* Match: override this F-card */
2930 assert(zFile);
2931 if(manifest_file_mperm(zFile)==PERM_LNK){
2932 goto err_no_symlink;
2933 }
2934 ++iFCursor;
2935 zFilename = zFile->zName
2936 /* use original name in case of name-case difference */;
2937 }else{/* This is a new file */
2938 zFilename = pCI->zFilename;
2939 }
2940 postProcess = 2;
2941 }
2942 }else{/* Non-delta: write F-cards which lexically preceed
2943 pCI->zFilename */
2944 cmp = -1;
2945 while((zFile = manifest_file_next(pCI->pParent, 0))
2946 && (cmp = fncmp(zFile->zName, pCI->zFilename))<0){
2947 blob_appendf(pOut, "F %F %s%s\n", zFile->zName, zFile->zUuid,
2948 mfile_perm_mstring(zFile));
2949 }
2950 if(cmp==0){/* Match: override this F-card*/
2951 if(manifest_file_mperm(zFile)==PERM_LNK){
2952 goto err_no_symlink;
2953 }
2954 zFilename = zFile->zName
2955 /* use original name in case of name-case difference */;
2956 }else{/* This is a new file. */
2957 zFilename = pCI->zFilename;
2958 if(zFile!=0){
2959 assert(cmp>0);
2960 assert(pCI->pParent->iFile>0);
2961 --pCI->pParent->iFile
2962 /* So that the post-processing loop picks up this file
2963 again.*/;
@@ -2964,44 +2984,38 @@
2964 }
2965 }
2966 postProcess = 1;
2967 }
2968 /* Finally add the new file's F-card... */
2969 zFile = 0;
2970 zUuid = blob_str(&pCI->fileHash);
2971 assert(zFilename);
2972 assert(zUuid);
2973 assert(postProcess==0 || postProcess==1 || postProcess==2);
2974 blob_appendf(pOut, "F %F %s%s\n", zFilename, zUuid,
2975 mfile_permint_mstring(pCI->filePerm));
2976 while(postProcess>0){
2977 /* Write F-cards which lexically follow pCI->zFilename */
2978 if(postProcess==1){ /* non-delta parent */
2979 zFile = manifest_file_next(pCI->pParent, 0);
2980 }else{ /* clone directly from delta parent */
2981 zFile = iFCursor<pCI->pParent->nFile
2982 ? &pCI->pParent->aFile[iFCursor++] : 0;
2983 }
2984 if(zFile==0){
2985 break;
2986 }
2987 #ifndef NDEBUG
2988 cmp = fncmp(zFile->zName, pCI->zFilename);
2989 assert(cmp>0);
2990 if(cmp<=0){
2991 mf_err((pErr,"Internal error: mis-ordering of "
2992 "F-cards detected."));
2993 }
2994 #endif
2995 if(zFile->zUuid){
2996 blob_appendf(pOut, "F %F %s%s\n", zFile->zName, zFile->zUuid,
2997 mfile_perm_mstring(zFile));
2998 }else{
2999 assert(postProcess==2);
3000 /* File was removed from parent delta. */
3001 blob_appendf(pOut, "F %F\n", zFile->zName);
3002 }
3003 }
3004 return 1;
3005 err_no_symlink:
3006 mf_err((pErr,"Cannot commit or overwrite symlinks "
3007 "via mini-checkin."));
@@ -3316,14 +3330,20 @@
3316 if(create_manifest_mini(&mf, pCI, pErr)==0){
3317 return 0;
3318 }
3319 isPrivate = content_is_private(pCI->pParent->rid);
3320 rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
3321 content_deltify(rid, &pCI->pParent->rid, 1, 0);
3322 if(pCI->flags & CIMINI_DUMP_MANIFEST){
3323 fossil_print("Manifest %z:\n%b", rid_to_uuid(rid), &mf);
 
 
 
 
 
 
3324 }
 
3325 manifest_crosslink(rid, &mf, 0);
3326 blob_reset(&mf);
3327 /* Save and deltify the file content... */
3328 frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
3329 0, 0, isPrivate);
@@ -3388,11 +3408,14 @@
3388 ** --allow-new-file Allow addition of a new file this way.
3389 ** Disabled by default to avoid that case-
3390 ** sensitivity errors inadvertently lead to
3391 ** adding a new file where an update is
3392 ** intended.
3393 ** --dump-manifest|-d Dumps the generated manifest to stdout.
 
 
 
3394 ** --wet-run Disables the default dry-run mode.
3395 **
3396 ** Example:
3397 **
3398 ** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c
@@ -3406,10 +3429,11 @@
3406 const char * zCommentFile; /* -M FILE */
3407 const char * zAsFilename; /* --as filename */
3408 const char * zRevision; /* --revision|-r [=trunk|checkout] */
3409 const char * zUser; /* --user-override */
3410 const char * zDate; /* --date-override */
 
3411
3412 /* This function should perform only the minimal "business logic" it
3413 ** needs in order to fully/properly populate the CheckinMiniInfo and
3414 ** then pass it on to checkin_mini() to do most of the validation
3415 ** and work. The point of this is to avoid duplicate code when a web
@@ -3420,10 +3444,11 @@
3420 zCommentFile = find_option("comment-file","M",1);
3421 zAsFilename = find_option("as",0,1);
3422 zRevision = find_option("revision","r",1);
3423 zUser = find_option("user-override",0,1);
3424 zDate = find_option("date-override",0,1);
 
3425 if(find_option("wet-run",0,0)==0){
3426 cinf.flags |= CIMINI_DRY_RUN;
3427 }
3428 if(find_option("allow-fork",0,0)!=0){
3429 cinf.flags |= CIMINI_ALLOW_FORK;
@@ -3466,10 +3491,11 @@
3466 }
3467 if(!blob_size(&cinf.comment)){
3468 fossil_fatal("Non-empty checkin comment is required.");
3469 }
3470 }
 
3471 zFilename = g.argv[2];
3472 cinf.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename);
3473 cinf.filePerm = file_perm(zFilename, ExtFILE);
3474 cinf.zUser = mprintf("%s", zUser ? zUser : login_name());
3475 if(zDate){
@@ -3484,24 +3510,43 @@
3484 }
3485 name_to_uuid2(zRevision, "ci", &cinf.zParentUuid);
3486 if(cinf.zParentUuid==0){
3487 fossil_fatal("Cannot determine version to commit to.");
3488 }
3489 blob_read_from_file(&cinf.fileContent, zFilename,
3490 ExtFILE/*may want to reconsider*/);
3491 {
 
3492 Blob errMsg = empty_blob;
3493 const int rc = checkin_mini(&cinf, &newRid, &errMsg);
3494 CheckinMiniInfo_cleanup(&cinf);
 
 
 
3495 if(rc){
3496 assert(blob_size(&errMsg)==0);
3497 }else{
3498 assert(blob_size(&errMsg));
3499 fossil_fatal("%b", &errMsg);
3500 }
 
 
 
 
 
 
 
 
 
 
 
3501 }
 
 
 
 
3502 if(!(cinf.flags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){
3503 fossil_warning("The checkout state is now out of sync "
3504 "with regards to this commit. It needs to be "
3505 "'update'd or 'close'd and re-'open'ed.");
3506 }
 
3507 }
3508
--- src/checkin.c
+++ src/checkin.c
@@ -2697,72 +2697,49 @@
2697 }
2698 }
2699
2700 /*
2701 ** State for the "mini-checkin" infrastructure, which enables the
2702 ** ability to commit changes to a single file without a checkout
2703 ** db, e.g. for use via an HTTP request.
2704 **
2705 ** Memory for all non-const (char *) members is owned by the
2706 ** CheckinMiniInfo instance and is freed by CheckinMiniInfo_cleanup().
2707 */
2708 struct CheckinMiniInfo {
2709 Manifest * pParent; /* parent checkin. Memory is owned by this
2710 object. */
2711 char *zParentUuid; /* UUID of pParent */
 
 
 
 
 
 
2712 char *zFilename; /* Name of single file to commit. Must be
2713 relative to the top of the repo. */
2714 Blob fileContent; /* Content of file referred to by zFilename. */
2715 Blob fileHash; /* Hash of this->fileContent, using the repo's
2716 preferred hash method. */
2717 Blob comment; /* Check-in comment text */
2718 char *zMimetype; /* Mimetype of comment. May be NULL */
2719 char *zUser; /* User name */
2720 char *zDate; /* Optionally force this date string (anything
2721 supported by date_in_standard_format()).
2722 Maybe be NULL. */
2723 Blob *pMfOut; /* If not NULL, checkin_mini() will write a
2724 copy of the generated manifest here. This
2725 memory is NOT owned by CheckinMiniInfo. */
2726 int filePerm; /* Permissions (via file_perm()) of the input
2727 file. We need to store this before calling
2728 checkin_mini() because the real input file
2729 name may differ from the repo-centric
2730 this->zFilename, and checkin_mini() requires
2731 the permissions of the original file. For
2732 web commits, set this to PERM_REG or (when
2733 editing executable scripts) PERM_EXE before
2734 calling checkin_mini(). */
2735 int flags; /* Bitmask of fossil_cimini_flags. */
 
2736 };
2737 typedef struct CheckinMiniInfo CheckinMiniInfo;
2738
2739 /*
2740 ** CheckinMiniInfo::flags values.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2741 */
2742 enum fossil_cimini_flags {
2743 CIMINI_NONE = 0,
2744 /*
2745 ** Tells checkin_mini() to use dry-run mode.
@@ -2824,10 +2801,38 @@
2801 ** the inadvertent addition of a new file when an update to an
2802 ** existing was intended, as a side-effect of name-case differences.
2803 */
2804 CIMINI_ALLOW_NEW_FILE = 1<<8
2805 };
2806
2807 /*
2808 ** Initializes p to a known-valid default state.
2809 */
2810 static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
2811 memset(p, 0, sizeof(CheckinMiniInfo));
2812 p->flags = CIMINI_NONE;
2813 p->filePerm = -1;
2814 p->comment = p->fileContent = p->fileHash = empty_blob;
2815 }
2816
2817 /*
2818 ** Frees all memory owned by p, but does not free p.
2819 */
2820 static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
2821 blob_reset(&p->comment);
2822 blob_reset(&p->fileContent);
2823 blob_reset(&p->fileHash);
2824 if(p->pParent){
2825 manifest_destroy(p->pParent);
2826 }
2827 fossil_free(p->zFilename);
2828 fossil_free(p->zMimetype);
2829 fossil_free(p->zParentUuid);
2830 fossil_free(p->zUser);
2831 fossil_free(p->zDate);
2832 CheckinMiniInfo_init(p);
2833 }
2834
2835 /*
2836 ** Internal helper which returns an F-card perms string suitable for
2837 ** writing into a manifest.
2838 */
@@ -2840,10 +2845,31 @@
2845 }
2846
2847 static const char * mfile_perm_mstring(const ManifestFile * p){
2848 return mfile_permint_mstring(manifest_file_mperm(p));
2849 }
2850
2851 /*
2852 ** Internal helper for checkin_mini() and friends. Appends an F-card
2853 ** for p to pOut.
2854 */
2855 static void checkin_mini_append_fcard(Blob *pOut, const ManifestFile *p){
2856 if(p->zUuid){
2857 assert(*p->zUuid);
2858 blob_appendf(pOut, "F %F %s%s", p->zName,
2859 p->zUuid, mfile_perm_mstring(p));
2860 if(p->zPrior){
2861 assert(*p->zPrior);
2862 blob_appendf(pOut, " %F\n", p->zPrior);
2863 }else{
2864 blob_append(pOut, "\n", 1);
2865 }
2866 }else{
2867 /* File was removed from parent delta. */
2868 blob_appendf(pOut, "F %F\n", p->zName);
2869 }
2870 }
2871
2872 /*
2873 ** Handles the F-card parts for create_manifest_mini().
2874 **
2875 ** If asDelta is true, F-cards will be handled as for a delta
@@ -2855,11 +2881,11 @@
2881 */
2882 static int create_manifest_mini_fcards( Blob * pOut,
2883 CheckinMiniInfo * pCI,
2884 int asDelta,
2885 Blob * pErr){
2886 ManifestFile *pFile; /* One file entry from pCI->pParent */
2887 const char *zFilename = 0; /* filename for new F-card */
2888 const char *zUuid = 0; /* UUID for new F-card */
2889 int cmp = 0; /* filename comparison result */
2890 int iFCursor = 0; /* Cursor into pCI->pParent->aFile if
2891 pCI->pParent is a delta. */
@@ -2882,18 +2908,18 @@
2908 if(asDelta){
2909 if(pCI->pParent->zBaseline==0 || pCI->pParent->nFile==0 ){
2910 /* Parent is a baseline or a delta with no F-cards, so this is
2911 ** the simplest case: create a delta with a single F-card.
2912 */
2913 pFile = manifest_file_find(pCI->pParent, pCI->zFilename);
2914 if(pFile==0){/* New file */
2915 zFilename = pCI->zFilename;
2916 }else{/* Replacement file */
2917 if(manifest_file_mperm(pFile)==PERM_LNK){
2918 goto err_no_symlink;
2919 }
2920 zFilename = pFile->zName
2921 /* use original name in case of name-case difference */;
2922 }
2923 postProcess = 0;
2924 }else{
2925 /* Parent is a delta manifest with F-cards. Traversal of delta
@@ -2907,57 +2933,51 @@
2933 */
2934 Manifest * p = pCI->pParent;
2935 cmp = -1;
2936 assert(p->nFile > 0);
2937 iFCursor = 0;
2938 pFile = &p->aFile[iFCursor];
2939 /* Write F-cards which lexically preceed pCI->zFilename */
2940 for( ; iFCursor<p->nFile; ){
2941 pFile = &p->aFile[iFCursor];
2942 cmp = fncmp(pFile->zName, pCI->zFilename);
2943 if(cmp<0){
2944 ++iFCursor;
2945 checkin_mini_append_fcard(pOut,pFile);
 
 
 
 
 
2946 }else{
2947 break;
2948 }
2949 }
2950 if(0==cmp){/* Match: override this F-card */
2951 assert(pFile);
2952 if(manifest_file_mperm(pFile)==PERM_LNK){
2953 goto err_no_symlink;
2954 }
2955 ++iFCursor;
2956 zFilename = pFile->zName
2957 /* use original name in case of name-case difference */;
2958 }else{/* This is a new file */
2959 zFilename = pCI->zFilename;
2960 }
2961 postProcess = 2;
2962 }
2963 }else{/* Non-delta: write F-cards which lexically preceed
2964 pCI->zFilename */
2965 cmp = -1;
2966 while((pFile = manifest_file_next(pCI->pParent, 0))
2967 && (cmp = fncmp(pFile->zName, pCI->zFilename))<0){
2968 checkin_mini_append_fcard(pOut,pFile);
 
2969 }
2970 if(cmp==0){/* Match: override this F-card*/
2971 if(manifest_file_mperm(pFile)==PERM_LNK){
2972 goto err_no_symlink;
2973 }
2974 zFilename = pFile->zName
2975 /* use original name in case of name-case difference */;
2976 }else{/* This is a new file. */
2977 zFilename = pCI->zFilename;
2978 if(pFile!=0){
2979 assert(cmp>0);
2980 assert(pCI->pParent->iFile>0);
2981 --pCI->pParent->iFile
2982 /* So that the post-processing loop picks up this file
2983 again.*/;
@@ -2964,44 +2984,38 @@
2984 }
2985 }
2986 postProcess = 1;
2987 }
2988 /* Finally add the new file's F-card... */
2989 pFile = 0;
2990 zUuid = blob_str(&pCI->fileHash);
2991 assert(zFilename);
2992 assert(zUuid);
2993 assert(postProcess==0 || postProcess==1 || postProcess==2);
2994 blob_appendf(pOut, "F %F %s%s\n", zFilename, zUuid,
2995 mfile_permint_mstring(pCI->filePerm));
2996 while(postProcess>0){
2997 /* Write F-cards which lexically follow pCI->zFilename */
2998 if(postProcess==1){ /* non-delta parent */
2999 pFile = manifest_file_next(pCI->pParent, 0);
3000 }else{ /* clone directly from delta parent */
3001 pFile = iFCursor<pCI->pParent->nFile
3002 ? &pCI->pParent->aFile[iFCursor++] : 0;
3003 }
3004 if(pFile==0){
3005 break;
3006 }
3007 #ifndef NDEBUG
3008 cmp = fncmp(pFile->zName, pCI->zFilename);
3009 assert(cmp>0);
3010 if(cmp<=0){
3011 mf_err((pErr,"Internal error: mis-ordering of "
3012 "F-cards detected."));
3013 }
3014 #endif
3015 assert(pFile->zUuid || 2==postProcess);
3016 checkin_mini_append_fcard(pOut,pFile);
 
 
 
 
 
 
3017 }
3018 return 1;
3019 err_no_symlink:
3020 mf_err((pErr,"Cannot commit or overwrite symlinks "
3021 "via mini-checkin."));
@@ -3316,14 +3330,20 @@
3330 if(create_manifest_mini(&mf, pCI, pErr)==0){
3331 return 0;
3332 }
3333 isPrivate = content_is_private(pCI->pParent->rid);
3334 rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
 
3335 if(pCI->flags & CIMINI_DUMP_MANIFEST){
3336 fossil_print("%b", &mf);
3337 }
3338 if(pCI->pMfOut!=0){
3339 /* Cross-linking clears mf, so we have to copy it,
3340 ** instead of taking over its memory. */
3341 blob_reset(pCI->pMfOut);
3342 blob_append(pCI->pMfOut, blob_buffer(&mf), blob_size(&mf));
3343 }
3344 content_deltify(rid, &pCI->pParent->rid, 1, 0);
3345 manifest_crosslink(rid, &mf, 0);
3346 blob_reset(&mf);
3347 /* Save and deltify the file content... */
3348 frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
3349 0, 0, isPrivate);
@@ -3388,11 +3408,14 @@
3408 ** --allow-new-file Allow addition of a new file this way.
3409 ** Disabled by default to avoid that case-
3410 ** sensitivity errors inadvertently lead to
3411 ** adding a new file where an update is
3412 ** intended.
3413 ** --dump-manifest|-d Dumps the generated manifest to stdout
3414 ** immediately after it's generated.
3415 ** --save-manifest FILE Saves the generated manifest to a file
3416 ** after successfully processing it.
3417 ** --wet-run Disables the default dry-run mode.
3418 **
3419 ** Example:
3420 **
3421 ** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c
@@ -3406,10 +3429,11 @@
3429 const char * zCommentFile; /* -M FILE */
3430 const char * zAsFilename; /* --as filename */
3431 const char * zRevision; /* --revision|-r [=trunk|checkout] */
3432 const char * zUser; /* --user-override */
3433 const char * zDate; /* --date-override */
3434 char const * zManifestFile = 0;/* --save-manifest FILE */
3435
3436 /* This function should perform only the minimal "business logic" it
3437 ** needs in order to fully/properly populate the CheckinMiniInfo and
3438 ** then pass it on to checkin_mini() to do most of the validation
3439 ** and work. The point of this is to avoid duplicate code when a web
@@ -3420,10 +3444,11 @@
3444 zCommentFile = find_option("comment-file","M",1);
3445 zAsFilename = find_option("as",0,1);
3446 zRevision = find_option("revision","r",1);
3447 zUser = find_option("user-override",0,1);
3448 zDate = find_option("date-override",0,1);
3449 zManifestFile = find_option("save-manifest",0,1);
3450 if(find_option("wet-run",0,0)==0){
3451 cinf.flags |= CIMINI_DRY_RUN;
3452 }
3453 if(find_option("allow-fork",0,0)!=0){
3454 cinf.flags |= CIMINI_ALLOW_FORK;
@@ -3466,10 +3491,11 @@
3491 }
3492 if(!blob_size(&cinf.comment)){
3493 fossil_fatal("Non-empty checkin comment is required.");
3494 }
3495 }
3496 db_begin_transaction();
3497 zFilename = g.argv[2];
3498 cinf.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename);
3499 cinf.filePerm = file_perm(zFilename, ExtFILE);
3500 cinf.zUser = mprintf("%s", zUser ? zUser : login_name());
3501 if(zDate){
@@ -3484,24 +3510,43 @@
3510 }
3511 name_to_uuid2(zRevision, "ci", &cinf.zParentUuid);
3512 if(cinf.zParentUuid==0){
3513 fossil_fatal("Cannot determine version to commit to.");
3514 }
3515 blob_read_from_file(&cinf.fileContent, zFilename, ExtFILE);
 
3516 {
3517 Blob theManifest = empty_blob; /* --save-manifest target */
3518 Blob errMsg = empty_blob;
3519 int rc;
3520 if(zManifestFile){
3521 cinf.pMfOut = &theManifest;
3522 }
3523 rc = checkin_mini(&cinf, &newRid, &errMsg);
3524 if(rc){
3525 assert(blob_size(&errMsg)==0);
3526 }else{
3527 assert(blob_size(&errMsg));
3528 fossil_fatal("%b", &errMsg);
3529 }
3530 if(zManifestFile){
3531 fossil_print("Writing manifest to: %s\n", zManifestFile);
3532 assert(blob_size(&theManifest)>0);
3533 blob_write_to_file(&theManifest, zManifestFile);
3534 blob_reset(&theManifest);
3535 }
3536 }
3537 if(newRid!=0){
3538 fossil_print("New version%s: %z\n",
3539 (cinf.flags & CIMINI_DRY_RUN) ? " (dry run)" : "",
3540 rid_to_uuid(newRid));
3541 }
3542 db_end_transaction(0/*checkin_mini() will have triggered it to roll
3543 ** back in dry-run mode, but we need access to
3544 ** the transaction-written db state in this
3545 ** routine.*/);
3546 if(!(cinf.flags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){
3547 fossil_warning("The checkout state is now out of sync "
3548 "with regards to this commit. It needs to be "
3549 "'update'd or 'close'd and re-'open'ed.");
3550 }
3551 CheckinMiniInfo_cleanup(&cinf);
3552 }
3553

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button