Fossil SCM

Renamed the various "one" pieces to "mini", e.g. checkin_mini().

stephan 2020-04-29 11:17 checkin-without-checkout
Commit d84c5149164fc0870c7360683beb2942caabfd72c9d2defe4c0cd472167fcdfc
1 file changed +72 -66
+72 -66
--- src/checkin.c
+++ src/checkin.c
@@ -2676,13 +2676,13 @@
26762676
/*
26772677
** State for the "web-checkin" infrastructure, which enables the
26782678
** ability to commit changes to a single file via an HTTP request.
26792679
**
26802680
** Memory for all non-const (char *) members is owned by the
2681
-** CheckinOneFileInfo instance.
2681
+** CheckinMiniInfo instance.
26822682
*/
2683
-struct CheckinOneFileInfo {
2683
+struct CheckinMiniInfo {
26842684
Blob comment; /* Check-in comment text */
26852685
char *zMimetype; /* Mimetype of check-in command. May be NULL */
26862686
Manifest * pParent; /* parent checkin */
26872687
char *zParentUuid; /* UUID of pParent */
26882688
char *zUser; /* User name */
@@ -2694,23 +2694,23 @@
26942694
relative to the top of the repo. */
26952695
Blob fileContent; /* Content of file referred to by zFilename. */
26962696
Blob fileHash; /* Hash of this->fileContent, using the
26972697
repo's preferred hash method. */
26982698
};
2699
-typedef struct CheckinOneFileInfo CheckinOneFileInfo;
2699
+typedef struct CheckinMiniInfo CheckinMiniInfo;
27002700
/*
27012701
** Initializes p to a known-valid default state.
27022702
*/
2703
-static void CheckinOneFileInfo_init( CheckinOneFileInfo * p ){
2704
- memset(p, 0, sizeof(CheckinOneFileInfo));
2703
+static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
2704
+ memset(p, 0, sizeof(CheckinMiniInfo));
27052705
p->comment = p->fileContent = p->fileHash = empty_blob;
27062706
}
27072707
27082708
/*
27092709
** Frees all memory owned by p, but does not free p.
27102710
*/
2711
-static void CheckinOneFileInfo_cleanup( CheckinOneFileInfo * p ){
2711
+static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
27122712
blob_reset(&p->comment);
27132713
blob_reset(&p->fileContent);
27142714
blob_reset(&p->fileHash);
27152715
if(p->pParent){
27162716
manifest_destroy(p->pParent);
@@ -2718,40 +2718,40 @@
27182718
fossil_free(p->zFilename);
27192719
fossil_free(p->zMimetype);
27202720
fossil_free(p->zParentUuid);
27212721
fossil_free(p->zUser);
27222722
fossil_free(p->zDate);
2723
- CheckinOneFileInfo_init(p);
2723
+ CheckinMiniInfo_init(p);
27242724
}
27252725
27262726
/*
2727
-** Flags for checkin_one_file()
2728
-*/
2729
-enum fossil_ckin1_flags {
2730
-/*
2731
-** Tells checkin_one_file() to use dry-run mode.
2732
-*/
2733
-CKIN1_DRY_RUN = 1,
2734
-/*
2735
-** Tells checkin_one_file() to allow forking from a non-leaf commit.
2736
-*/
2737
-CKIN1_ALLOW_FORK = 1<<1,
2738
-/*
2739
-** Tells checkin_one_file() to dump its generated manifest to stdout.
2740
-*/
2741
-CKIN1_DUMP_MANIFEST = 1<<2,
2727
+** Flags for checkin_mini()
2728
+*/
2729
+enum fossil_cimini_flags {
2730
+/*
2731
+** Tells checkin_mini() to use dry-run mode.
2732
+*/
2733
+CIMINI_DRY_RUN = 1,
2734
+/*
2735
+** Tells checkin_mini() to allow forking from a non-leaf commit.
2736
+*/
2737
+CIMINI_ALLOW_FORK = 1<<1,
2738
+/*
2739
+** Tells checkin_mini() to dump its generated manifest to stdout.
2740
+*/
2741
+CIMINI_DUMP_MANIFEST = 1<<2,
27422742
27432743
/*
27442744
** By default, content containing what appears to be a merge conflict
27452745
** marker is not permitted. This flag relaxes that requirement.
27462746
*/
2747
-CKIN1_ALLOW_MERGE_MARKER = 1<<3,
2747
+CIMINI_ALLOW_MERGE_MARKER = 1<<3,
27482748
27492749
/*
27502750
** NOT YET IMPLEMENTED.
27512751
*/
2752
-CKIN1_ALLOW_CLOSED_LEAF = 1<<4
2752
+CIMINI_ALLOW_CLOSED_LEAF = 1<<4
27532753
};
27542754
27552755
/*
27562756
** Creates a manifest file, written to pOut, from the state in the
27572757
** fully-populated pCI argument. pCI is not *semantically* modified
@@ -2759,13 +2759,12 @@
27592759
** any given blob.
27602760
**
27612761
** Returns true on success. On error, returns 0 and, if pErr is not
27622762
** NULL, writes an error message there.
27632763
*/
2764
-static int create_manifest_one_file( Blob * pOut,
2765
- CheckinOneFileInfo * pCI,
2766
- Blob * pErr){
2764
+static int create_manifest_mini( Blob * pOut, CheckinMiniInfo * pCI,
2765
+ Blob * pErr){
27672766
Blob zCard = empty_blob; /* Z-card checksum */
27682767
ManifestFile *zFile; /* One file entry from the pCI->pParent*/
27692768
int cmp = -99; /* filename comparison result */
27702769
int fperm = 0; /* file permissions */
27712770
const char *zPerm = 0; /* permissions for new F-card */
@@ -2881,35 +2880,42 @@
28812880
}
28822881
28832882
/*
28842883
** EXPERIMENTAL! Subject to change or removal at any time.
28852884
**
2886
-** A so-called "single-file checkin" is a slimmed-down form of the
2887
-** checkin command which accepts only a single file and is intended to
2888
-** accept edits to a file via the web interface or from the CLI from
2889
-** outside of a checkout.
2885
+** A so-called "single-file/mini/web checkin" is a slimmed-down form
2886
+** of the checkin command which accepts only a single file and is
2887
+** intended to accept edits to a file via the web interface or from
2888
+** the CLI from outside of a checkout.
2889
+**
2890
+** Being fully non-interactive is a requirement for this function,
2891
+** thus it cannot perform autosync or similar activities.
28902892
**
28912893
** This routine uses the state from the given fully-populated pCI
28922894
** argument to add pCI->fileContent to the database, and create and
28932895
** save a manifest for that change. Ownership of pCI and its contents
28942896
** are unchanged.
28952897
**
28962898
** If pCI->fileHash is empty, this routine populates it with the
2897
-** repository's preferred hash algorithm.
2899
+** repository's preferred hash algorithm. pCI is not otherwise
2900
+** modified, nor is its ownership modified.
2901
+**
2902
+** This function validates several of the inputs and fails if any
2903
+** validation fails.
28982904
**
28992905
** On error, returns false (0) and, if pErr is not NULL, writes a
29002906
** diagnostic message there.
29012907
**
29022908
** Returns true on success. If pRid is not NULL, the RID of the
29032909
** resulting manifest is written to *pRid.
29042910
**
2905
-** ckin1Flags is a bitmask of optional flags from fossil_ckin1_flags
2911
+** ciminiFlags is a bitmask of optional flags from fossil_cimini_flags
29062912
** enum. See that enum for the docs for each flag. Pass 0 for no
29072913
** flags.
29082914
*/
2909
-static int checkin_one_file( CheckinOneFileInfo * pCI, int *pRid,
2910
- int ckin1Flags, Blob * pErr ){
2915
+static int checkin_mini( CheckinMiniInfo * pCI, int *pRid,
2916
+ int ciminiFlags, Blob * pErr ){
29112917
Blob mf = empty_blob; /* output manifest */
29122918
int rid = 0, frid = 0; /* various RIDs */
29132919
const int isPrivate = content_is_private(pCI->pParent->rid);
29142920
ManifestFile * zFile; /* file from pCI->pParent */;
29152921
const char * zFilePrevUuid = 0; /* UUID of previous version of
@@ -2927,23 +2933,19 @@
29272933
** no reason we can't do that via the generated manifest,
29282934
** but the commit command does not offer that option, so
29292935
** we won't, either.
29302936
*/
29312937
}
2932
- if(!(CKIN1_ALLOW_FORK & ckin1Flags)
2933
- && !is_a_leaf(pCI->pParent->rid)){
2938
+ if(!(CIMINI_ALLOW_FORK & ciminiFlags)
2939
+ && !is_a_leaf(pCI->pParent->rid)){
29342940
ci_err((pErr,"Parent [%S] is not a leaf and forking is disabled.",
29352941
pCI->zParentUuid));
29362942
}
2937
- if(!(CKIN1_ALLOW_MERGE_MARKER & ckin1Flags)
2938
- && contains_merge_marker(&pCI->fileContent)){
2943
+ if(!(CIMINI_ALLOW_MERGE_MARKER & ciminiFlags)
2944
+ && contains_merge_marker(&pCI->fileContent)){
29392945
ci_err((pErr,"Content appears to contain a merge conflict marker."));
29402946
}
2941
- if(blob_size(&pCI->fileHash)==0){
2942
- hname_hash(&pCI->fileContent, 0, &pCI->fileHash);
2943
- assert(blob_size(&pCI->fileHash)>0);
2944
- }
29452947
/* Potential TODOs include:
29462948
**
29472949
** - Commit allows an empty checkin only with a flag, but we
29482950
** currently disallow it entirely. Conform with commit?
29492951
**
@@ -2955,11 +2957,13 @@
29552957
** Confirm that pCI->zFilename can be found in pCI->pParent. If
29562958
** not, fail. This is admittedly an artificial limitation, not
29572959
** strictly necessary. We do it to hopefully reduce the chance of an
29582960
** "oops" where file X/Y/z gets committed as X/Y/Z due to a typo or
29592961
** case-sensitivity mismatch between the user/repo/filesystem, or
2960
- ** some such.
2962
+ ** some such. That said, the remainder of this function is written
2963
+ ** as if this check did not exist, so enabling it "should" just be a
2964
+ ** matter of removing this check or guarding it with a flag.
29612965
*/
29622966
manifest_file_rewind(pCI->pParent);
29632967
zFile = manifest_file_seek(pCI->pParent, pCI->zFilename, 0);
29642968
if(!zFile){
29652969
ci_err((pErr,"File [%s] not found in manifest [%S]. "
@@ -2971,46 +2975,48 @@
29712975
if(0==fossil_strcmp(zFile->zUuid, blob_str(&pCI->fileHash))){
29722976
ci_err((pErr,"File is unchanged. Not saving."));
29732977
}
29742978
zFilePrevUuid = zFile->zUuid;
29752979
}
2980
+ if(blob_size(&pCI->fileHash)==0){
2981
+ hname_hash(&pCI->fileContent, 0, &pCI->fileHash);
2982
+ assert(blob_size(&pCI->fileHash)>0);
2983
+ }
29762984
/* Create the manifest... */
2977
- if(create_manifest_one_file(&mf, pCI, pErr)==0){
2985
+ if(create_manifest_mini(&mf, pCI, pErr)==0){
29782986
return 0;
29792987
}
2980
- /* Add the file content to the db... */
2988
+ /* Save and deltify the file content... */
29812989
frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
29822990
0, 0, isPrivate);
29832991
if(zFilePrevUuid!=0){
2984
- /* Deltify against previous file version... */
2985
- int prevFRid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q",
2986
- zFilePrevUuid);
2992
+ int prevFRid = fast_uuid_to_rid(zFilePrevUuid);
29872993
assert(prevFRid>0);
29882994
content_deltify(frid, &prevFRid, 1, 0);
29892995
}
29902996
/* Save, deltify, and crosslink the manifest... */
29912997
rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
29922998
content_deltify(rid, &pCI->pParent->rid, 1, 0);
29932999
if(pRid!=0){
29943000
*pRid = rid;
29953001
}
2996
- if( ckin1Flags & CKIN1_DUMP_MANIFEST ){
3002
+ if(ciminiFlags & CIMINI_DUMP_MANIFEST){
29973003
fossil_print("Manifest: %z\n%b", rid_to_uuid(rid), &mf);
29983004
}
29993005
manifest_crosslink(rid, &mf, 0);
30003006
blob_reset(&mf);
3001
- db_end_transaction((CKIN1_DRY_RUN & ckin1Flags) ? 1 : 0);
3007
+ db_end_transaction((CIMINI_DRY_RUN & ciminiFlags) ? 1 : 0);
30023008
return 1;
30033009
ci_error:
30043010
assert(db_transaction_nesting_depth()>0);
30053011
db_end_transaction(1);
30063012
return 0;
30073013
#undef ci_err
30083014
}
30093015
30103016
/*
3011
-** COMMAND: test-ci-one
3017
+** COMMAND: test-ci-mini
30123018
**
30133019
** This is an on-going experiment, subject to change or removal at
30143020
** any time.
30153021
**
30163022
** Usage: %fossil ?OPTIONS? FILENAME
@@ -3027,55 +3033,55 @@
30273033
** --comment|-m COMMENT Required checkin comment.
30283034
** --comment-file|-M FILE Reads checkin comment from the given file.
30293035
** --revision|-r VERSION Commit from this version. Default is
30303036
** the checkout version (if available) or
30313037
** trunk (if used without a checkout).
3032
-** --wet-run Disables the default dry-run mode.
30333038
** --allow-fork Allows the commit to be made against a
30343039
** non-leaf parent. Note that no autosync
30353040
** is performed beforehand.
30363041
** --allow-merge-conflict Allows checkin of a file even if it appears
30373042
** to contain a fossil merge conflict marker.
30383043
** --user-override USER USER to use instead of the current default.
30393044
** --date-override DATETIME DATE to use instead of 'now'.
30403045
** --dump-manifest|-d Dumps the generated manifest to stdout.
3046
+** --wet-run Disables the default dry-run mode.
30413047
**
30423048
** Example:
30433049
**
3044
-** %fossil test-ci-one -R REPO -m ... -r foo --as src/myfile.c myfile.c
3050
+** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c
30453051
**
30463052
*/
3047
-void test_ci_one_cmd(){
3048
- CheckinOneFileInfo cinf; /* checkin state */
3053
+void test_ci_mini_cmd(){
3054
+ CheckinMiniInfo cinf; /* checkin state */
30493055
int newRid = 0; /* RID of new version */
30503056
const char * zFilename; /* argv[2] */
30513057
const char * zComment; /* -m comment */
30523058
const char * zCommentFile; /* -M FILE */
30533059
const char * zAsFilename; /* --as filename */
30543060
const char * zRevision; /* --revision|-r [=trunk|checkout] */
30553061
const char * zUser; /* --user-override */
30563062
const char * zDate; /* --date-override */
3057
- int ckin1Flags = 0; /* flags for checkin_one_file(). */
3063
+ int ciminiFlags = 0; /* flags for checkin_mini(). */
30583064
3059
- CheckinOneFileInfo_init(&cinf);
3065
+ CheckinMiniInfo_init(&cinf);
30603066
zComment = find_option("comment","m",1);
30613067
zCommentFile = find_option("comment-file","M",1);
30623068
zAsFilename = find_option("as",0,1);
30633069
zRevision = find_option("revision","r",1);
30643070
zUser = find_option("user-override",0,1);
30653071
zDate = find_option("date-override",0,1);
30663072
if(find_option("wet-run",0,0)==0){
3067
- ckin1Flags |= CKIN1_DRY_RUN;
3073
+ ciminiFlags |= CIMINI_DRY_RUN;
30683074
}
30693075
if(find_option("allow-fork",0,0)!=0){
3070
- ckin1Flags |= CKIN1_ALLOW_FORK;
3076
+ ciminiFlags |= CIMINI_ALLOW_FORK;
30713077
}
30723078
if(find_option("dump-manifest","d",0)!=0){
3073
- ckin1Flags |= CKIN1_DUMP_MANIFEST;
3079
+ ciminiFlags |= CIMINI_DUMP_MANIFEST;
30743080
}
30753081
if(find_option("allow-merge-conflict",0,0)!=0){
3076
- ckin1Flags |= CKIN1_ALLOW_MERGE_MARKER;
3082
+ ciminiFlags |= CIMINI_ALLOW_MERGE_MARKER;
30773083
}
30783084
30793085
db_find_and_open_repository(0, 0);
30803086
verify_all_options();
30813087
user_select();
@@ -3107,11 +3113,11 @@
31073113
fossil_fatal("Non-empty checkin comment is required.");
31083114
}
31093115
}
31103116
31113117
zFilename = g.argv[2];
3112
- cinf.zFilename = mprintf("%s", zAsFilename ? zAsFilename : zFilename);
3118
+ cinf.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename);
31133119
cinf.zUser = mprintf("%s", zUser ? zUser : login_name());
31143120
if(zDate){
31153121
cinf.zDate = mprintf("%s", zDate);
31163122
}
31173123
if(zRevision==0 || zRevision[0]==0){
@@ -3129,21 +3135,21 @@
31293135
assert(cinf.pParent!=0);
31303136
blob_read_from_file(&cinf.fileContent, zFilename,
31313137
ExtFILE/*may want to reconsider*/);
31323138
{
31333139
Blob errMsg = empty_blob;
3134
- const int rc = checkin_one_file(&cinf, &newRid, ckin1Flags,
3140
+ const int rc = checkin_mini(&cinf, &newRid, ciminiFlags,
31353141
&errMsg);
3136
- CheckinOneFileInfo_cleanup(&cinf);
3142
+ CheckinMiniInfo_cleanup(&cinf);
31373143
if(rc){
31383144
assert(blob_size(&errMsg)==0);
31393145
}else{
31403146
assert(blob_size(&errMsg));
31413147
fossil_fatal("%b", &errMsg);
31423148
}
31433149
}
3144
- if(!(ckin1Flags & CKIN1_DRY_RUN) && newRid!=0 && g.localOpen!=0){
3150
+ if(!(ciminiFlags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){
31453151
fossil_warning("The checkout state is now out of sync "
31463152
"with regards to this commit. It needs to be "
31473153
"'update'd or 'close'd and re-'open'ed.");
31483154
}
31493155
}
31503156
--- src/checkin.c
+++ src/checkin.c
@@ -2676,13 +2676,13 @@
2676 /*
2677 ** State for the "web-checkin" infrastructure, which enables the
2678 ** ability to commit changes to a single file via an HTTP request.
2679 **
2680 ** Memory for all non-const (char *) members is owned by the
2681 ** CheckinOneFileInfo instance.
2682 */
2683 struct CheckinOneFileInfo {
2684 Blob comment; /* Check-in comment text */
2685 char *zMimetype; /* Mimetype of check-in command. May be NULL */
2686 Manifest * pParent; /* parent checkin */
2687 char *zParentUuid; /* UUID of pParent */
2688 char *zUser; /* User name */
@@ -2694,23 +2694,23 @@
2694 relative to the top of the repo. */
2695 Blob fileContent; /* Content of file referred to by zFilename. */
2696 Blob fileHash; /* Hash of this->fileContent, using the
2697 repo's preferred hash method. */
2698 };
2699 typedef struct CheckinOneFileInfo CheckinOneFileInfo;
2700 /*
2701 ** Initializes p to a known-valid default state.
2702 */
2703 static void CheckinOneFileInfo_init( CheckinOneFileInfo * p ){
2704 memset(p, 0, sizeof(CheckinOneFileInfo));
2705 p->comment = p->fileContent = p->fileHash = empty_blob;
2706 }
2707
2708 /*
2709 ** Frees all memory owned by p, but does not free p.
2710 */
2711 static void CheckinOneFileInfo_cleanup( CheckinOneFileInfo * p ){
2712 blob_reset(&p->comment);
2713 blob_reset(&p->fileContent);
2714 blob_reset(&p->fileHash);
2715 if(p->pParent){
2716 manifest_destroy(p->pParent);
@@ -2718,40 +2718,40 @@
2718 fossil_free(p->zFilename);
2719 fossil_free(p->zMimetype);
2720 fossil_free(p->zParentUuid);
2721 fossil_free(p->zUser);
2722 fossil_free(p->zDate);
2723 CheckinOneFileInfo_init(p);
2724 }
2725
2726 /*
2727 ** Flags for checkin_one_file()
2728 */
2729 enum fossil_ckin1_flags {
2730 /*
2731 ** Tells checkin_one_file() to use dry-run mode.
2732 */
2733 CKIN1_DRY_RUN = 1,
2734 /*
2735 ** Tells checkin_one_file() to allow forking from a non-leaf commit.
2736 */
2737 CKIN1_ALLOW_FORK = 1<<1,
2738 /*
2739 ** Tells checkin_one_file() to dump its generated manifest to stdout.
2740 */
2741 CKIN1_DUMP_MANIFEST = 1<<2,
2742
2743 /*
2744 ** By default, content containing what appears to be a merge conflict
2745 ** marker is not permitted. This flag relaxes that requirement.
2746 */
2747 CKIN1_ALLOW_MERGE_MARKER = 1<<3,
2748
2749 /*
2750 ** NOT YET IMPLEMENTED.
2751 */
2752 CKIN1_ALLOW_CLOSED_LEAF = 1<<4
2753 };
2754
2755 /*
2756 ** Creates a manifest file, written to pOut, from the state in the
2757 ** fully-populated pCI argument. pCI is not *semantically* modified
@@ -2759,13 +2759,12 @@
2759 ** any given blob.
2760 **
2761 ** Returns true on success. On error, returns 0 and, if pErr is not
2762 ** NULL, writes an error message there.
2763 */
2764 static int create_manifest_one_file( Blob * pOut,
2765 CheckinOneFileInfo * pCI,
2766 Blob * pErr){
2767 Blob zCard = empty_blob; /* Z-card checksum */
2768 ManifestFile *zFile; /* One file entry from the pCI->pParent*/
2769 int cmp = -99; /* filename comparison result */
2770 int fperm = 0; /* file permissions */
2771 const char *zPerm = 0; /* permissions for new F-card */
@@ -2881,35 +2880,42 @@
2881 }
2882
2883 /*
2884 ** EXPERIMENTAL! Subject to change or removal at any time.
2885 **
2886 ** A so-called "single-file checkin" is a slimmed-down form of the
2887 ** checkin command which accepts only a single file and is intended to
2888 ** accept edits to a file via the web interface or from the CLI from
2889 ** outside of a checkout.
 
 
 
2890 **
2891 ** This routine uses the state from the given fully-populated pCI
2892 ** argument to add pCI->fileContent to the database, and create and
2893 ** save a manifest for that change. Ownership of pCI and its contents
2894 ** are unchanged.
2895 **
2896 ** If pCI->fileHash is empty, this routine populates it with the
2897 ** repository's preferred hash algorithm.
 
 
 
 
2898 **
2899 ** On error, returns false (0) and, if pErr is not NULL, writes a
2900 ** diagnostic message there.
2901 **
2902 ** Returns true on success. If pRid is not NULL, the RID of the
2903 ** resulting manifest is written to *pRid.
2904 **
2905 ** ckin1Flags is a bitmask of optional flags from fossil_ckin1_flags
2906 ** enum. See that enum for the docs for each flag. Pass 0 for no
2907 ** flags.
2908 */
2909 static int checkin_one_file( CheckinOneFileInfo * pCI, int *pRid,
2910 int ckin1Flags, Blob * pErr ){
2911 Blob mf = empty_blob; /* output manifest */
2912 int rid = 0, frid = 0; /* various RIDs */
2913 const int isPrivate = content_is_private(pCI->pParent->rid);
2914 ManifestFile * zFile; /* file from pCI->pParent */;
2915 const char * zFilePrevUuid = 0; /* UUID of previous version of
@@ -2927,23 +2933,19 @@
2927 ** no reason we can't do that via the generated manifest,
2928 ** but the commit command does not offer that option, so
2929 ** we won't, either.
2930 */
2931 }
2932 if(!(CKIN1_ALLOW_FORK & ckin1Flags)
2933 && !is_a_leaf(pCI->pParent->rid)){
2934 ci_err((pErr,"Parent [%S] is not a leaf and forking is disabled.",
2935 pCI->zParentUuid));
2936 }
2937 if(!(CKIN1_ALLOW_MERGE_MARKER & ckin1Flags)
2938 && contains_merge_marker(&pCI->fileContent)){
2939 ci_err((pErr,"Content appears to contain a merge conflict marker."));
2940 }
2941 if(blob_size(&pCI->fileHash)==0){
2942 hname_hash(&pCI->fileContent, 0, &pCI->fileHash);
2943 assert(blob_size(&pCI->fileHash)>0);
2944 }
2945 /* Potential TODOs include:
2946 **
2947 ** - Commit allows an empty checkin only with a flag, but we
2948 ** currently disallow it entirely. Conform with commit?
2949 **
@@ -2955,11 +2957,13 @@
2955 ** Confirm that pCI->zFilename can be found in pCI->pParent. If
2956 ** not, fail. This is admittedly an artificial limitation, not
2957 ** strictly necessary. We do it to hopefully reduce the chance of an
2958 ** "oops" where file X/Y/z gets committed as X/Y/Z due to a typo or
2959 ** case-sensitivity mismatch between the user/repo/filesystem, or
2960 ** some such.
 
 
2961 */
2962 manifest_file_rewind(pCI->pParent);
2963 zFile = manifest_file_seek(pCI->pParent, pCI->zFilename, 0);
2964 if(!zFile){
2965 ci_err((pErr,"File [%s] not found in manifest [%S]. "
@@ -2971,46 +2975,48 @@
2971 if(0==fossil_strcmp(zFile->zUuid, blob_str(&pCI->fileHash))){
2972 ci_err((pErr,"File is unchanged. Not saving."));
2973 }
2974 zFilePrevUuid = zFile->zUuid;
2975 }
 
 
 
 
2976 /* Create the manifest... */
2977 if(create_manifest_one_file(&mf, pCI, pErr)==0){
2978 return 0;
2979 }
2980 /* Add the file content to the db... */
2981 frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
2982 0, 0, isPrivate);
2983 if(zFilePrevUuid!=0){
2984 /* Deltify against previous file version... */
2985 int prevFRid = db_int(0,"SELECT rid FROM blob WHERE uuid=%Q",
2986 zFilePrevUuid);
2987 assert(prevFRid>0);
2988 content_deltify(frid, &prevFRid, 1, 0);
2989 }
2990 /* Save, deltify, and crosslink the manifest... */
2991 rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
2992 content_deltify(rid, &pCI->pParent->rid, 1, 0);
2993 if(pRid!=0){
2994 *pRid = rid;
2995 }
2996 if( ckin1Flags & CKIN1_DUMP_MANIFEST ){
2997 fossil_print("Manifest: %z\n%b", rid_to_uuid(rid), &mf);
2998 }
2999 manifest_crosslink(rid, &mf, 0);
3000 blob_reset(&mf);
3001 db_end_transaction((CKIN1_DRY_RUN & ckin1Flags) ? 1 : 0);
3002 return 1;
3003 ci_error:
3004 assert(db_transaction_nesting_depth()>0);
3005 db_end_transaction(1);
3006 return 0;
3007 #undef ci_err
3008 }
3009
3010 /*
3011 ** COMMAND: test-ci-one
3012 **
3013 ** This is an on-going experiment, subject to change or removal at
3014 ** any time.
3015 **
3016 ** Usage: %fossil ?OPTIONS? FILENAME
@@ -3027,55 +3033,55 @@
3027 ** --comment|-m COMMENT Required checkin comment.
3028 ** --comment-file|-M FILE Reads checkin comment from the given file.
3029 ** --revision|-r VERSION Commit from this version. Default is
3030 ** the checkout version (if available) or
3031 ** trunk (if used without a checkout).
3032 ** --wet-run Disables the default dry-run mode.
3033 ** --allow-fork Allows the commit to be made against a
3034 ** non-leaf parent. Note that no autosync
3035 ** is performed beforehand.
3036 ** --allow-merge-conflict Allows checkin of a file even if it appears
3037 ** to contain a fossil merge conflict marker.
3038 ** --user-override USER USER to use instead of the current default.
3039 ** --date-override DATETIME DATE to use instead of 'now'.
3040 ** --dump-manifest|-d Dumps the generated manifest to stdout.
 
3041 **
3042 ** Example:
3043 **
3044 ** %fossil test-ci-one -R REPO -m ... -r foo --as src/myfile.c myfile.c
3045 **
3046 */
3047 void test_ci_one_cmd(){
3048 CheckinOneFileInfo cinf; /* checkin state */
3049 int newRid = 0; /* RID of new version */
3050 const char * zFilename; /* argv[2] */
3051 const char * zComment; /* -m comment */
3052 const char * zCommentFile; /* -M FILE */
3053 const char * zAsFilename; /* --as filename */
3054 const char * zRevision; /* --revision|-r [=trunk|checkout] */
3055 const char * zUser; /* --user-override */
3056 const char * zDate; /* --date-override */
3057 int ckin1Flags = 0; /* flags for checkin_one_file(). */
3058
3059 CheckinOneFileInfo_init(&cinf);
3060 zComment = find_option("comment","m",1);
3061 zCommentFile = find_option("comment-file","M",1);
3062 zAsFilename = find_option("as",0,1);
3063 zRevision = find_option("revision","r",1);
3064 zUser = find_option("user-override",0,1);
3065 zDate = find_option("date-override",0,1);
3066 if(find_option("wet-run",0,0)==0){
3067 ckin1Flags |= CKIN1_DRY_RUN;
3068 }
3069 if(find_option("allow-fork",0,0)!=0){
3070 ckin1Flags |= CKIN1_ALLOW_FORK;
3071 }
3072 if(find_option("dump-manifest","d",0)!=0){
3073 ckin1Flags |= CKIN1_DUMP_MANIFEST;
3074 }
3075 if(find_option("allow-merge-conflict",0,0)!=0){
3076 ckin1Flags |= CKIN1_ALLOW_MERGE_MARKER;
3077 }
3078
3079 db_find_and_open_repository(0, 0);
3080 verify_all_options();
3081 user_select();
@@ -3107,11 +3113,11 @@
3107 fossil_fatal("Non-empty checkin comment is required.");
3108 }
3109 }
3110
3111 zFilename = g.argv[2];
3112 cinf.zFilename = mprintf("%s", zAsFilename ? zAsFilename : zFilename);
3113 cinf.zUser = mprintf("%s", zUser ? zUser : login_name());
3114 if(zDate){
3115 cinf.zDate = mprintf("%s", zDate);
3116 }
3117 if(zRevision==0 || zRevision[0]==0){
@@ -3129,21 +3135,21 @@
3129 assert(cinf.pParent!=0);
3130 blob_read_from_file(&cinf.fileContent, zFilename,
3131 ExtFILE/*may want to reconsider*/);
3132 {
3133 Blob errMsg = empty_blob;
3134 const int rc = checkin_one_file(&cinf, &newRid, ckin1Flags,
3135 &errMsg);
3136 CheckinOneFileInfo_cleanup(&cinf);
3137 if(rc){
3138 assert(blob_size(&errMsg)==0);
3139 }else{
3140 assert(blob_size(&errMsg));
3141 fossil_fatal("%b", &errMsg);
3142 }
3143 }
3144 if(!(ckin1Flags & CKIN1_DRY_RUN) && newRid!=0 && g.localOpen!=0){
3145 fossil_warning("The checkout state is now out of sync "
3146 "with regards to this commit. It needs to be "
3147 "'update'd or 'close'd and re-'open'ed.");
3148 }
3149 }
3150
--- src/checkin.c
+++ src/checkin.c
@@ -2676,13 +2676,13 @@
2676 /*
2677 ** State for the "web-checkin" infrastructure, which enables the
2678 ** ability to commit changes to a single file via an HTTP request.
2679 **
2680 ** Memory for all non-const (char *) members is owned by the
2681 ** CheckinMiniInfo instance.
2682 */
2683 struct CheckinMiniInfo {
2684 Blob comment; /* Check-in comment text */
2685 char *zMimetype; /* Mimetype of check-in command. May be NULL */
2686 Manifest * pParent; /* parent checkin */
2687 char *zParentUuid; /* UUID of pParent */
2688 char *zUser; /* User name */
@@ -2694,23 +2694,23 @@
2694 relative to the top of the repo. */
2695 Blob fileContent; /* Content of file referred to by zFilename. */
2696 Blob fileHash; /* Hash of this->fileContent, using the
2697 repo's preferred hash method. */
2698 };
2699 typedef struct CheckinMiniInfo CheckinMiniInfo;
2700 /*
2701 ** Initializes p to a known-valid default state.
2702 */
2703 static void CheckinMiniInfo_init( CheckinMiniInfo * p ){
2704 memset(p, 0, sizeof(CheckinMiniInfo));
2705 p->comment = p->fileContent = p->fileHash = empty_blob;
2706 }
2707
2708 /*
2709 ** Frees all memory owned by p, but does not free p.
2710 */
2711 static void CheckinMiniInfo_cleanup( CheckinMiniInfo * p ){
2712 blob_reset(&p->comment);
2713 blob_reset(&p->fileContent);
2714 blob_reset(&p->fileHash);
2715 if(p->pParent){
2716 manifest_destroy(p->pParent);
@@ -2718,40 +2718,40 @@
2718 fossil_free(p->zFilename);
2719 fossil_free(p->zMimetype);
2720 fossil_free(p->zParentUuid);
2721 fossil_free(p->zUser);
2722 fossil_free(p->zDate);
2723 CheckinMiniInfo_init(p);
2724 }
2725
2726 /*
2727 ** Flags for checkin_mini()
2728 */
2729 enum fossil_cimini_flags {
2730 /*
2731 ** Tells checkin_mini() to use dry-run mode.
2732 */
2733 CIMINI_DRY_RUN = 1,
2734 /*
2735 ** Tells checkin_mini() to allow forking from a non-leaf commit.
2736 */
2737 CIMINI_ALLOW_FORK = 1<<1,
2738 /*
2739 ** Tells checkin_mini() to dump its generated manifest to stdout.
2740 */
2741 CIMINI_DUMP_MANIFEST = 1<<2,
2742
2743 /*
2744 ** By default, content containing what appears to be a merge conflict
2745 ** marker is not permitted. This flag relaxes that requirement.
2746 */
2747 CIMINI_ALLOW_MERGE_MARKER = 1<<3,
2748
2749 /*
2750 ** NOT YET IMPLEMENTED.
2751 */
2752 CIMINI_ALLOW_CLOSED_LEAF = 1<<4
2753 };
2754
2755 /*
2756 ** Creates a manifest file, written to pOut, from the state in the
2757 ** fully-populated pCI argument. pCI is not *semantically* modified
@@ -2759,13 +2759,12 @@
2759 ** any given blob.
2760 **
2761 ** Returns true on success. On error, returns 0 and, if pErr is not
2762 ** NULL, writes an error message there.
2763 */
2764 static int create_manifest_mini( Blob * pOut, CheckinMiniInfo * pCI,
2765 Blob * pErr){
 
2766 Blob zCard = empty_blob; /* Z-card checksum */
2767 ManifestFile *zFile; /* One file entry from the pCI->pParent*/
2768 int cmp = -99; /* filename comparison result */
2769 int fperm = 0; /* file permissions */
2770 const char *zPerm = 0; /* permissions for new F-card */
@@ -2881,35 +2880,42 @@
2880 }
2881
2882 /*
2883 ** EXPERIMENTAL! Subject to change or removal at any time.
2884 **
2885 ** A so-called "single-file/mini/web checkin" is a slimmed-down form
2886 ** of the checkin command which accepts only a single file and is
2887 ** intended to accept edits to a file via the web interface or from
2888 ** the CLI from outside of a checkout.
2889 **
2890 ** Being fully non-interactive is a requirement for this function,
2891 ** thus it cannot perform autosync or similar activities.
2892 **
2893 ** This routine uses the state from the given fully-populated pCI
2894 ** argument to add pCI->fileContent to the database, and create and
2895 ** save a manifest for that change. Ownership of pCI and its contents
2896 ** are unchanged.
2897 **
2898 ** If pCI->fileHash is empty, this routine populates it with the
2899 ** repository's preferred hash algorithm. pCI is not otherwise
2900 ** modified, nor is its ownership modified.
2901 **
2902 ** This function validates several of the inputs and fails if any
2903 ** validation fails.
2904 **
2905 ** On error, returns false (0) and, if pErr is not NULL, writes a
2906 ** diagnostic message there.
2907 **
2908 ** Returns true on success. If pRid is not NULL, the RID of the
2909 ** resulting manifest is written to *pRid.
2910 **
2911 ** ciminiFlags is a bitmask of optional flags from fossil_cimini_flags
2912 ** enum. See that enum for the docs for each flag. Pass 0 for no
2913 ** flags.
2914 */
2915 static int checkin_mini( CheckinMiniInfo * pCI, int *pRid,
2916 int ciminiFlags, Blob * pErr ){
2917 Blob mf = empty_blob; /* output manifest */
2918 int rid = 0, frid = 0; /* various RIDs */
2919 const int isPrivate = content_is_private(pCI->pParent->rid);
2920 ManifestFile * zFile; /* file from pCI->pParent */;
2921 const char * zFilePrevUuid = 0; /* UUID of previous version of
@@ -2927,23 +2933,19 @@
2933 ** no reason we can't do that via the generated manifest,
2934 ** but the commit command does not offer that option, so
2935 ** we won't, either.
2936 */
2937 }
2938 if(!(CIMINI_ALLOW_FORK & ciminiFlags)
2939 && !is_a_leaf(pCI->pParent->rid)){
2940 ci_err((pErr,"Parent [%S] is not a leaf and forking is disabled.",
2941 pCI->zParentUuid));
2942 }
2943 if(!(CIMINI_ALLOW_MERGE_MARKER & ciminiFlags)
2944 && contains_merge_marker(&pCI->fileContent)){
2945 ci_err((pErr,"Content appears to contain a merge conflict marker."));
2946 }
 
 
 
 
2947 /* Potential TODOs include:
2948 **
2949 ** - Commit allows an empty checkin only with a flag, but we
2950 ** currently disallow it entirely. Conform with commit?
2951 **
@@ -2955,11 +2957,13 @@
2957 ** Confirm that pCI->zFilename can be found in pCI->pParent. If
2958 ** not, fail. This is admittedly an artificial limitation, not
2959 ** strictly necessary. We do it to hopefully reduce the chance of an
2960 ** "oops" where file X/Y/z gets committed as X/Y/Z due to a typo or
2961 ** case-sensitivity mismatch between the user/repo/filesystem, or
2962 ** some such. That said, the remainder of this function is written
2963 ** as if this check did not exist, so enabling it "should" just be a
2964 ** matter of removing this check or guarding it with a flag.
2965 */
2966 manifest_file_rewind(pCI->pParent);
2967 zFile = manifest_file_seek(pCI->pParent, pCI->zFilename, 0);
2968 if(!zFile){
2969 ci_err((pErr,"File [%s] not found in manifest [%S]. "
@@ -2971,46 +2975,48 @@
2975 if(0==fossil_strcmp(zFile->zUuid, blob_str(&pCI->fileHash))){
2976 ci_err((pErr,"File is unchanged. Not saving."));
2977 }
2978 zFilePrevUuid = zFile->zUuid;
2979 }
2980 if(blob_size(&pCI->fileHash)==0){
2981 hname_hash(&pCI->fileContent, 0, &pCI->fileHash);
2982 assert(blob_size(&pCI->fileHash)>0);
2983 }
2984 /* Create the manifest... */
2985 if(create_manifest_mini(&mf, pCI, pErr)==0){
2986 return 0;
2987 }
2988 /* Save and deltify the file content... */
2989 frid = content_put_ex(&pCI->fileContent, blob_str(&pCI->fileHash),
2990 0, 0, isPrivate);
2991 if(zFilePrevUuid!=0){
2992 int prevFRid = fast_uuid_to_rid(zFilePrevUuid);
 
 
2993 assert(prevFRid>0);
2994 content_deltify(frid, &prevFRid, 1, 0);
2995 }
2996 /* Save, deltify, and crosslink the manifest... */
2997 rid = content_put_ex(&mf, 0, 0, 0, isPrivate);
2998 content_deltify(rid, &pCI->pParent->rid, 1, 0);
2999 if(pRid!=0){
3000 *pRid = rid;
3001 }
3002 if(ciminiFlags & CIMINI_DUMP_MANIFEST){
3003 fossil_print("Manifest: %z\n%b", rid_to_uuid(rid), &mf);
3004 }
3005 manifest_crosslink(rid, &mf, 0);
3006 blob_reset(&mf);
3007 db_end_transaction((CIMINI_DRY_RUN & ciminiFlags) ? 1 : 0);
3008 return 1;
3009 ci_error:
3010 assert(db_transaction_nesting_depth()>0);
3011 db_end_transaction(1);
3012 return 0;
3013 #undef ci_err
3014 }
3015
3016 /*
3017 ** COMMAND: test-ci-mini
3018 **
3019 ** This is an on-going experiment, subject to change or removal at
3020 ** any time.
3021 **
3022 ** Usage: %fossil ?OPTIONS? FILENAME
@@ -3027,55 +3033,55 @@
3033 ** --comment|-m COMMENT Required checkin comment.
3034 ** --comment-file|-M FILE Reads checkin comment from the given file.
3035 ** --revision|-r VERSION Commit from this version. Default is
3036 ** the checkout version (if available) or
3037 ** trunk (if used without a checkout).
 
3038 ** --allow-fork Allows the commit to be made against a
3039 ** non-leaf parent. Note that no autosync
3040 ** is performed beforehand.
3041 ** --allow-merge-conflict Allows checkin of a file even if it appears
3042 ** to contain a fossil merge conflict marker.
3043 ** --user-override USER USER to use instead of the current default.
3044 ** --date-override DATETIME DATE to use instead of 'now'.
3045 ** --dump-manifest|-d Dumps the generated manifest to stdout.
3046 ** --wet-run Disables the default dry-run mode.
3047 **
3048 ** Example:
3049 **
3050 ** %fossil test-ci-mini -R REPO -m ... -r foo --as src/myfile.c myfile.c
3051 **
3052 */
3053 void test_ci_mini_cmd(){
3054 CheckinMiniInfo cinf; /* checkin state */
3055 int newRid = 0; /* RID of new version */
3056 const char * zFilename; /* argv[2] */
3057 const char * zComment; /* -m comment */
3058 const char * zCommentFile; /* -M FILE */
3059 const char * zAsFilename; /* --as filename */
3060 const char * zRevision; /* --revision|-r [=trunk|checkout] */
3061 const char * zUser; /* --user-override */
3062 const char * zDate; /* --date-override */
3063 int ciminiFlags = 0; /* flags for checkin_mini(). */
3064
3065 CheckinMiniInfo_init(&cinf);
3066 zComment = find_option("comment","m",1);
3067 zCommentFile = find_option("comment-file","M",1);
3068 zAsFilename = find_option("as",0,1);
3069 zRevision = find_option("revision","r",1);
3070 zUser = find_option("user-override",0,1);
3071 zDate = find_option("date-override",0,1);
3072 if(find_option("wet-run",0,0)==0){
3073 ciminiFlags |= CIMINI_DRY_RUN;
3074 }
3075 if(find_option("allow-fork",0,0)!=0){
3076 ciminiFlags |= CIMINI_ALLOW_FORK;
3077 }
3078 if(find_option("dump-manifest","d",0)!=0){
3079 ciminiFlags |= CIMINI_DUMP_MANIFEST;
3080 }
3081 if(find_option("allow-merge-conflict",0,0)!=0){
3082 ciminiFlags |= CIMINI_ALLOW_MERGE_MARKER;
3083 }
3084
3085 db_find_and_open_repository(0, 0);
3086 verify_all_options();
3087 user_select();
@@ -3107,11 +3113,11 @@
3113 fossil_fatal("Non-empty checkin comment is required.");
3114 }
3115 }
3116
3117 zFilename = g.argv[2];
3118 cinf.zFilename = mprintf("%/", zAsFilename ? zAsFilename : zFilename);
3119 cinf.zUser = mprintf("%s", zUser ? zUser : login_name());
3120 if(zDate){
3121 cinf.zDate = mprintf("%s", zDate);
3122 }
3123 if(zRevision==0 || zRevision[0]==0){
@@ -3129,21 +3135,21 @@
3135 assert(cinf.pParent!=0);
3136 blob_read_from_file(&cinf.fileContent, zFilename,
3137 ExtFILE/*may want to reconsider*/);
3138 {
3139 Blob errMsg = empty_blob;
3140 const int rc = checkin_mini(&cinf, &newRid, ciminiFlags,
3141 &errMsg);
3142 CheckinMiniInfo_cleanup(&cinf);
3143 if(rc){
3144 assert(blob_size(&errMsg)==0);
3145 }else{
3146 assert(blob_size(&errMsg));
3147 fossil_fatal("%b", &errMsg);
3148 }
3149 }
3150 if(!(ciminiFlags & CIMINI_DRY_RUN) && newRid!=0 && g.localOpen!=0){
3151 fossil_warning("The checkout state is now out of sync "
3152 "with regards to this commit. It needs to be "
3153 "'update'd or 'close'd and re-'open'ed.");
3154 }
3155 }
3156

Keyboard Shortcuts

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