Fossil SCM

Enhance the "reconstruct" command so that sets the correct hash policy for artifacts read from disk.

drh 2019-02-05 15:43 trunk merge
Commit 93bb323192ab7db60478f85777e205e0f3a496fb263b1b863868cd0f343112bb
1 file changed +172 -6
+172 -6
--- src/rebuild.c
+++ src/rebuild.c
@@ -182,11 +182,14 @@
182182
static int processCnt; /* Number processed so far */
183183
static int ttyOutput; /* Do progress output */
184184
static Bag bagDone; /* Bag of records rebuilt */
185185
186186
static char *zFNameFormat; /* Format string for filenames on deconstruct */
187
+static int cchFNamePrefix; /* Length of directory prefix in zFNameFormat */
188
+static char *zDestDir; /* Destination directory on deconstruct */
187189
static int prefixLength; /* Length of directory prefix for deconstruct */
190
+static int fKeepRid1; /* Flag to preserve RID=1 on de- and reconstruct */
188191
189192
190193
/*
191194
** Draw the percent-complete message.
192195
** The input is actually the permill complete.
@@ -274,10 +277,21 @@
274277
/* We are doing "fossil deconstruct" */
275278
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
276279
char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/,
277280
zUuid, zUuid+prefixLength);
278281
blob_write_to_file(pUse,zFile);
282
+ if( rid==1 && fKeepRid1!=0 ){
283
+ char *zFnDotRid1 = mprintf("%s/.rid1", zDestDir);
284
+ char *zFnRid1 = zFile + cchFNamePrefix + 1; /* Skip directory slash */
285
+ Blob bFileContents = empty_blob;
286
+ blob_appendf(&bFileContents,
287
+ "# The file holding the artifact with RID=1\n"
288
+ "%s\n", zFnRid1);
289
+ blob_write_to_file(&bFileContents, zFnDotRid1);
290
+ blob_reset(&bFileContents);
291
+ free(zFnDotRid1);
292
+ }
279293
free(zFile);
280294
free(zUuid);
281295
blob_reset(pUse);
282296
}
283297
assert( blob_is_reset(pUse) );
@@ -931,11 +945,50 @@
931945
struct dirent *pEntry;
932946
Blob aContent; /* content of the just read artifact */
933947
static int nFileRead = 0;
934948
void *zUnicodePath;
935949
char *zUtf8Name;
950
+ static int recursionLevel = 0; /* Bookkeeping about the recursion level */
951
+ static char *zFnRid1 = 0; /* The file holding the artifact with RID=1 */
952
+ static int cchPathInitial = 0; /* The length of zPath on first recursion */
936953
954
+ recursionLevel++;
955
+ if( recursionLevel==1 ){
956
+ cchPathInitial = strlen(zPath);
957
+ if( fKeepRid1!=0 ){
958
+ char *zFnDotRid1 = mprintf("%s/.rid1", zPath);
959
+ Blob bFileContents;
960
+ if( blob_read_from_file(&bFileContents, zFnDotRid1, ExtFILE)!=-1 ){
961
+ Blob line, value;
962
+ while( blob_line(&bFileContents, &line)>0 ){
963
+ if( blob_token(&line, &value)==0 ) continue; /* Empty line */
964
+ if( blob_buffer(&value)[0]=='#' ) continue; /* Comment */
965
+ blob_trim(&value);
966
+ zFnRid1 = mprintf("%s/%s", zPath, blob_str(&value));
967
+ break;
968
+ }
969
+ blob_reset(&bFileContents);
970
+ if( zFnRid1 ){
971
+ if( blob_read_from_file(&aContent, zFnRid1, ExtFILE)==-1 ){
972
+ fossil_fatal("some unknown error occurred while reading \"%s\"",
973
+ zFnRid1);
974
+ }else{
975
+ recon_set_hash_policy(0, zFnRid1);
976
+ content_put(&aContent);
977
+ recon_restore_hash_policy();
978
+ blob_reset(&aContent);
979
+ fossil_print("\r%d", ++nFileRead);
980
+ fflush(stdout);
981
+ }
982
+ }else{
983
+ fossil_fatal("an error occurred while reading or parsing \"%s\"",
984
+ zFnDotRid1);
985
+ }
986
+ }
987
+ free(zFnDotRid1);
988
+ }
989
+ }
937990
zUnicodePath = fossil_utf8_to_path(zPath, 1);
938991
d = opendir(zUnicodePath);
939992
if( d ){
940993
while( (pEntry=readdir(d))!=0 ){
941994
Blob path;
@@ -953,18 +1006,20 @@
9531006
#else
9541007
if( file_isdir(zSubpath, ExtFILE)==1 )
9551008
#endif
9561009
{
9571010
recon_read_dir(zSubpath);
958
- }else{
1011
+ }else if( fossil_strcmp(zSubpath, zFnRid1)!=0 ){
9591012
blob_init(&path, 0, 0);
9601013
blob_appendf(&path, "%s", zSubpath);
9611014
if( blob_read_from_file(&aContent, blob_str(&path), ExtFILE)==-1 ){
9621015
fossil_fatal("some unknown error occurred while reading \"%s\"",
9631016
blob_str(&path));
9641017
}
1018
+ recon_set_hash_policy(cchPathInitial, blob_str(&path));
9651019
content_put(&aContent);
1020
+ recon_restore_hash_policy();
9661021
blob_reset(&path);
9671022
blob_reset(&aContent);
9681023
fossil_print("\r%d", ++nFileRead);
9691024
fflush(stdout);
9701025
}
@@ -974,26 +1029,134 @@
9741029
}else {
9751030
fossil_fatal("encountered error %d while trying to open \"%s\".",
9761031
errno, g.argv[3]);
9771032
}
9781033
fossil_path_free(zUnicodePath);
1034
+ if( recursionLevel==1 && zFnRid1!=0 ) free(zFnRid1);
1035
+ recursionLevel--;
1036
+}
1037
+
1038
+/*
1039
+** Helper functions called from recon_read_dir() to set and restore the correct
1040
+** hash policy for an artifact read from disk, inferred from the length of the
1041
+** path name.
1042
+*/
1043
+static int saved_eHashPolicy = -1;
1044
+
1045
+void recon_set_hash_policy(
1046
+ const int cchPathPrefix, /* Directory prefix length for zUuidAsFilePath */
1047
+ const char *zUuidAsFilePath /* Relative, well-formed, from recon_read_dir() */
1048
+){
1049
+ int cchUuidAsFilePath;
1050
+ const char *zHashPart;
1051
+ int cchHashPart = 0;
1052
+ int new_eHashPolicy = -1;
1053
+ assert( HNAME_COUNT==2 ); /* Review function if new hashes are implemented. */
1054
+ if( zUuidAsFilePath==0 ) return;
1055
+ cchUuidAsFilePath = strlen(zUuidAsFilePath);
1056
+ if( cchUuidAsFilePath==0 ) return;
1057
+ if( cchPathPrefix>=cchUuidAsFilePath ) return;
1058
+ for( zHashPart = zUuidAsFilePath + cchPathPrefix; *zHashPart; zHashPart++ ){
1059
+ if( *zHashPart!='/' ) cchHashPart++;
1060
+ }
1061
+ if( cchHashPart>=HNAME_LEN_K256 ){
1062
+ new_eHashPolicy = HPOLICY_SHA3;
1063
+ }else if( cchHashPart>=HNAME_LEN_SHA1 ){
1064
+ new_eHashPolicy = HPOLICY_SHA1;
1065
+ }
1066
+ if( new_eHashPolicy!=-1 ){
1067
+ saved_eHashPolicy = g.eHashPolicy;
1068
+ g.eHashPolicy = new_eHashPolicy;
1069
+ }
1070
+}
1071
+
1072
+void recon_restore_hash_policy(){
1073
+ if( saved_eHashPolicy!=-1 ){
1074
+ g.eHashPolicy = saved_eHashPolicy;
1075
+ saved_eHashPolicy = -1;
1076
+ }
1077
+}
1078
+
1079
+#if 0
1080
+/*
1081
+** COMMAND: test-hash-from-path*
1082
+**
1083
+** Usage: %fossil test-hash-from-path ?OPTIONS? DESTINATION UUID
1084
+**
1085
+** Generate a sample path name from DESTINATION and UUID, as the `deconstruct'
1086
+** command would do. Then try to guess the hash policy from the path name, as
1087
+** the `reconstruct' command would do.
1088
+**
1089
+** No files or directories will be created.
1090
+**
1091
+** Options:
1092
+** -L|--prefixlength N Set the length of the names of the DESTINATION
1093
+** subdirectories to N.
1094
+*/
1095
+void test_hash_from_path_cmd(void) {
1096
+ char *zDest;
1097
+ char *zUuid;
1098
+ char *zFile;
1099
+ const char *zHashPolicy = "unknown";
1100
+ const char *zPrefixOpt = find_option("prefixlength","L",1);
1101
+ int iPrefixLength;
1102
+ if( !zPrefixOpt ){
1103
+ iPrefixLength = 2;
1104
+ }else{
1105
+ iPrefixLength = atoi(zPrefixOpt);
1106
+ if( iPrefixLength<0 || iPrefixLength>9 ){
1107
+ fossil_fatal("N(%s) is not a valid prefix length!",zPrefixOpt);
1108
+ }
1109
+ }
1110
+ if( g.argc!=4 ){
1111
+ usage ("?OPTIONS? DESTINATION UUID");
1112
+ }
1113
+ zDest = g.argv[2];
1114
+ zUuid = g.argv[3];
1115
+ if( iPrefixLength ){
1116
+ zFNameFormat = mprintf("%s/%%.%ds/%%s",zDest,iPrefixLength);
1117
+ }else{
1118
+ zFNameFormat = mprintf("%s/%%s",zDest);
1119
+ }
1120
+ cchFNamePrefix = strlen(zDest);
1121
+ zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/,
1122
+ zUuid, zUuid+iPrefixLength);
1123
+ recon_set_hash_policy(cchFNamePrefix,zFile);
1124
+ if( saved_eHashPolicy!=-1 ){
1125
+ zHashPolicy = hpolicy_name();
1126
+ }
1127
+ recon_restore_hash_policy();
1128
+ fossil_print(
1129
+ "\nPath Name: %s"
1130
+ "\nHash Policy: %s\n",
1131
+ zFile,zHashPolicy);
1132
+ free(zFile);
1133
+ free(zFNameFormat);
1134
+ zFNameFormat = 0;
1135
+ cchFNamePrefix = 0;
9791136
}
1137
+#endif
9801138
9811139
/*
9821140
** COMMAND: reconstruct*
9831141
**
984
-** Usage: %fossil reconstruct FILENAME DIRECTORY
1142
+** Usage: %fossil reconstruct ?OPTIONS? FILENAME DIRECTORY
9851143
**
9861144
** This command studies the artifacts (files) in DIRECTORY and
9871145
** reconstructs the fossil record from them. It places the new
9881146
** fossil repository in FILENAME. Subdirectories are read, files
9891147
** with leading '.' in the filename are ignored.
9901148
**
1149
+** Options:
1150
+** -K|--keep-rid1 Read the filename of the artifact with
1151
+** RID=1 from the file .rid in DIRECTORY.
1152
+**
9911153
** See also: deconstruct, rebuild
9921154
*/
9931155
void reconstruct_cmd(void) {
9941156
char *zPassword;
1157
+ fKeepRid1 = find_option("keep-rid1","K",0)!=0;
9951158
if( g.argc!=4 ){
9961159
usage("FILENAME DIRECTORY");
9971160
}
9981161
if( file_isdir(g.argv[3], ExtFILE)!=1 ){
9991162
fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
@@ -1041,23 +1204,25 @@
10411204
** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters.
10421205
** If -L|--prefixlength is given, the length (default 2) of the directory
10431206
** prefix can be set to 0,1,..,9 characters.
10441207
**
10451208
** Options:
1046
-** -R|--repository REPOSITORY deconstruct given REPOSITORY
1047
-** -L|--prefixlength N set the length of the names of the DESTINATION
1048
-** subdirectories to N
1209
+** -R|--repository REPOSITORY Deconstruct given REPOSITORY.
1210
+** -K|--keep-rid1 Save the filename of the artifact with RID=1 to
1211
+** the file .rid1 in the DESTINATION directory.
1212
+** -L|--prefixlength N Set the length of the names of the DESTINATION
1213
+** subdirectories to N.
10491214
** --private Include private artifacts.
10501215
**
10511216
** See also: rebuild, reconstruct
10521217
*/
10531218
void deconstruct_cmd(void){
1054
- const char *zDestDir;
10551219
const char *zPrefixOpt;
10561220
Stmt s;
10571221
int privateFlag;
10581222
1223
+ fKeepRid1 = find_option("keep-rid1","K",0)!=0;
10591224
/* get and check prefix length argument and build format string */
10601225
zPrefixOpt=find_option("prefixlength","L",1);
10611226
if( !zPrefixOpt ){
10621227
prefixLength = 2;
10631228
}else{
@@ -1092,10 +1257,11 @@
10921257
if( prefixLength ){
10931258
zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
10941259
}else{
10951260
zFNameFormat = mprintf("%s/%%s",zDestDir);
10961261
}
1262
+ cchFNamePrefix = strlen(zDestDir);
10971263
10981264
bag_init(&bagDone);
10991265
ttyOutput = 1;
11001266
processCnt = 0;
11011267
if (!g.fQuiet) {
11021268
--- src/rebuild.c
+++ src/rebuild.c
@@ -182,11 +182,14 @@
182 static int processCnt; /* Number processed so far */
183 static int ttyOutput; /* Do progress output */
184 static Bag bagDone; /* Bag of records rebuilt */
185
186 static char *zFNameFormat; /* Format string for filenames on deconstruct */
 
 
187 static int prefixLength; /* Length of directory prefix for deconstruct */
 
188
189
190 /*
191 ** Draw the percent-complete message.
192 ** The input is actually the permill complete.
@@ -274,10 +277,21 @@
274 /* We are doing "fossil deconstruct" */
275 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
276 char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/,
277 zUuid, zUuid+prefixLength);
278 blob_write_to_file(pUse,zFile);
 
 
 
 
 
 
 
 
 
 
 
279 free(zFile);
280 free(zUuid);
281 blob_reset(pUse);
282 }
283 assert( blob_is_reset(pUse) );
@@ -931,11 +945,50 @@
931 struct dirent *pEntry;
932 Blob aContent; /* content of the just read artifact */
933 static int nFileRead = 0;
934 void *zUnicodePath;
935 char *zUtf8Name;
 
 
 
936
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
937 zUnicodePath = fossil_utf8_to_path(zPath, 1);
938 d = opendir(zUnicodePath);
939 if( d ){
940 while( (pEntry=readdir(d))!=0 ){
941 Blob path;
@@ -953,18 +1006,20 @@
953 #else
954 if( file_isdir(zSubpath, ExtFILE)==1 )
955 #endif
956 {
957 recon_read_dir(zSubpath);
958 }else{
959 blob_init(&path, 0, 0);
960 blob_appendf(&path, "%s", zSubpath);
961 if( blob_read_from_file(&aContent, blob_str(&path), ExtFILE)==-1 ){
962 fossil_fatal("some unknown error occurred while reading \"%s\"",
963 blob_str(&path));
964 }
 
965 content_put(&aContent);
 
966 blob_reset(&path);
967 blob_reset(&aContent);
968 fossil_print("\r%d", ++nFileRead);
969 fflush(stdout);
970 }
@@ -974,26 +1029,134 @@
974 }else {
975 fossil_fatal("encountered error %d while trying to open \"%s\".",
976 errno, g.argv[3]);
977 }
978 fossil_path_free(zUnicodePath);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
979 }
 
980
981 /*
982 ** COMMAND: reconstruct*
983 **
984 ** Usage: %fossil reconstruct FILENAME DIRECTORY
985 **
986 ** This command studies the artifacts (files) in DIRECTORY and
987 ** reconstructs the fossil record from them. It places the new
988 ** fossil repository in FILENAME. Subdirectories are read, files
989 ** with leading '.' in the filename are ignored.
990 **
 
 
 
 
991 ** See also: deconstruct, rebuild
992 */
993 void reconstruct_cmd(void) {
994 char *zPassword;
 
995 if( g.argc!=4 ){
996 usage("FILENAME DIRECTORY");
997 }
998 if( file_isdir(g.argv[3], ExtFILE)!=1 ){
999 fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
@@ -1041,23 +1204,25 @@
1041 ** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters.
1042 ** If -L|--prefixlength is given, the length (default 2) of the directory
1043 ** prefix can be set to 0,1,..,9 characters.
1044 **
1045 ** Options:
1046 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
1047 ** -L|--prefixlength N set the length of the names of the DESTINATION
1048 ** subdirectories to N
 
 
1049 ** --private Include private artifacts.
1050 **
1051 ** See also: rebuild, reconstruct
1052 */
1053 void deconstruct_cmd(void){
1054 const char *zDestDir;
1055 const char *zPrefixOpt;
1056 Stmt s;
1057 int privateFlag;
1058
 
1059 /* get and check prefix length argument and build format string */
1060 zPrefixOpt=find_option("prefixlength","L",1);
1061 if( !zPrefixOpt ){
1062 prefixLength = 2;
1063 }else{
@@ -1092,10 +1257,11 @@
1092 if( prefixLength ){
1093 zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
1094 }else{
1095 zFNameFormat = mprintf("%s/%%s",zDestDir);
1096 }
 
1097
1098 bag_init(&bagDone);
1099 ttyOutput = 1;
1100 processCnt = 0;
1101 if (!g.fQuiet) {
1102
--- src/rebuild.c
+++ src/rebuild.c
@@ -182,11 +182,14 @@
182 static int processCnt; /* Number processed so far */
183 static int ttyOutput; /* Do progress output */
184 static Bag bagDone; /* Bag of records rebuilt */
185
186 static char *zFNameFormat; /* Format string for filenames on deconstruct */
187 static int cchFNamePrefix; /* Length of directory prefix in zFNameFormat */
188 static char *zDestDir; /* Destination directory on deconstruct */
189 static int prefixLength; /* Length of directory prefix for deconstruct */
190 static int fKeepRid1; /* Flag to preserve RID=1 on de- and reconstruct */
191
192
193 /*
194 ** Draw the percent-complete message.
195 ** The input is actually the permill complete.
@@ -274,10 +277,21 @@
277 /* We are doing "fossil deconstruct" */
278 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
279 char *zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/,
280 zUuid, zUuid+prefixLength);
281 blob_write_to_file(pUse,zFile);
282 if( rid==1 && fKeepRid1!=0 ){
283 char *zFnDotRid1 = mprintf("%s/.rid1", zDestDir);
284 char *zFnRid1 = zFile + cchFNamePrefix + 1; /* Skip directory slash */
285 Blob bFileContents = empty_blob;
286 blob_appendf(&bFileContents,
287 "# The file holding the artifact with RID=1\n"
288 "%s\n", zFnRid1);
289 blob_write_to_file(&bFileContents, zFnDotRid1);
290 blob_reset(&bFileContents);
291 free(zFnDotRid1);
292 }
293 free(zFile);
294 free(zUuid);
295 blob_reset(pUse);
296 }
297 assert( blob_is_reset(pUse) );
@@ -931,11 +945,50 @@
945 struct dirent *pEntry;
946 Blob aContent; /* content of the just read artifact */
947 static int nFileRead = 0;
948 void *zUnicodePath;
949 char *zUtf8Name;
950 static int recursionLevel = 0; /* Bookkeeping about the recursion level */
951 static char *zFnRid1 = 0; /* The file holding the artifact with RID=1 */
952 static int cchPathInitial = 0; /* The length of zPath on first recursion */
953
954 recursionLevel++;
955 if( recursionLevel==1 ){
956 cchPathInitial = strlen(zPath);
957 if( fKeepRid1!=0 ){
958 char *zFnDotRid1 = mprintf("%s/.rid1", zPath);
959 Blob bFileContents;
960 if( blob_read_from_file(&bFileContents, zFnDotRid1, ExtFILE)!=-1 ){
961 Blob line, value;
962 while( blob_line(&bFileContents, &line)>0 ){
963 if( blob_token(&line, &value)==0 ) continue; /* Empty line */
964 if( blob_buffer(&value)[0]=='#' ) continue; /* Comment */
965 blob_trim(&value);
966 zFnRid1 = mprintf("%s/%s", zPath, blob_str(&value));
967 break;
968 }
969 blob_reset(&bFileContents);
970 if( zFnRid1 ){
971 if( blob_read_from_file(&aContent, zFnRid1, ExtFILE)==-1 ){
972 fossil_fatal("some unknown error occurred while reading \"%s\"",
973 zFnRid1);
974 }else{
975 recon_set_hash_policy(0, zFnRid1);
976 content_put(&aContent);
977 recon_restore_hash_policy();
978 blob_reset(&aContent);
979 fossil_print("\r%d", ++nFileRead);
980 fflush(stdout);
981 }
982 }else{
983 fossil_fatal("an error occurred while reading or parsing \"%s\"",
984 zFnDotRid1);
985 }
986 }
987 free(zFnDotRid1);
988 }
989 }
990 zUnicodePath = fossil_utf8_to_path(zPath, 1);
991 d = opendir(zUnicodePath);
992 if( d ){
993 while( (pEntry=readdir(d))!=0 ){
994 Blob path;
@@ -953,18 +1006,20 @@
1006 #else
1007 if( file_isdir(zSubpath, ExtFILE)==1 )
1008 #endif
1009 {
1010 recon_read_dir(zSubpath);
1011 }else if( fossil_strcmp(zSubpath, zFnRid1)!=0 ){
1012 blob_init(&path, 0, 0);
1013 blob_appendf(&path, "%s", zSubpath);
1014 if( blob_read_from_file(&aContent, blob_str(&path), ExtFILE)==-1 ){
1015 fossil_fatal("some unknown error occurred while reading \"%s\"",
1016 blob_str(&path));
1017 }
1018 recon_set_hash_policy(cchPathInitial, blob_str(&path));
1019 content_put(&aContent);
1020 recon_restore_hash_policy();
1021 blob_reset(&path);
1022 blob_reset(&aContent);
1023 fossil_print("\r%d", ++nFileRead);
1024 fflush(stdout);
1025 }
@@ -974,26 +1029,134 @@
1029 }else {
1030 fossil_fatal("encountered error %d while trying to open \"%s\".",
1031 errno, g.argv[3]);
1032 }
1033 fossil_path_free(zUnicodePath);
1034 if( recursionLevel==1 && zFnRid1!=0 ) free(zFnRid1);
1035 recursionLevel--;
1036 }
1037
1038 /*
1039 ** Helper functions called from recon_read_dir() to set and restore the correct
1040 ** hash policy for an artifact read from disk, inferred from the length of the
1041 ** path name.
1042 */
1043 static int saved_eHashPolicy = -1;
1044
1045 void recon_set_hash_policy(
1046 const int cchPathPrefix, /* Directory prefix length for zUuidAsFilePath */
1047 const char *zUuidAsFilePath /* Relative, well-formed, from recon_read_dir() */
1048 ){
1049 int cchUuidAsFilePath;
1050 const char *zHashPart;
1051 int cchHashPart = 0;
1052 int new_eHashPolicy = -1;
1053 assert( HNAME_COUNT==2 ); /* Review function if new hashes are implemented. */
1054 if( zUuidAsFilePath==0 ) return;
1055 cchUuidAsFilePath = strlen(zUuidAsFilePath);
1056 if( cchUuidAsFilePath==0 ) return;
1057 if( cchPathPrefix>=cchUuidAsFilePath ) return;
1058 for( zHashPart = zUuidAsFilePath + cchPathPrefix; *zHashPart; zHashPart++ ){
1059 if( *zHashPart!='/' ) cchHashPart++;
1060 }
1061 if( cchHashPart>=HNAME_LEN_K256 ){
1062 new_eHashPolicy = HPOLICY_SHA3;
1063 }else if( cchHashPart>=HNAME_LEN_SHA1 ){
1064 new_eHashPolicy = HPOLICY_SHA1;
1065 }
1066 if( new_eHashPolicy!=-1 ){
1067 saved_eHashPolicy = g.eHashPolicy;
1068 g.eHashPolicy = new_eHashPolicy;
1069 }
1070 }
1071
1072 void recon_restore_hash_policy(){
1073 if( saved_eHashPolicy!=-1 ){
1074 g.eHashPolicy = saved_eHashPolicy;
1075 saved_eHashPolicy = -1;
1076 }
1077 }
1078
1079 #if 0
1080 /*
1081 ** COMMAND: test-hash-from-path*
1082 **
1083 ** Usage: %fossil test-hash-from-path ?OPTIONS? DESTINATION UUID
1084 **
1085 ** Generate a sample path name from DESTINATION and UUID, as the `deconstruct'
1086 ** command would do. Then try to guess the hash policy from the path name, as
1087 ** the `reconstruct' command would do.
1088 **
1089 ** No files or directories will be created.
1090 **
1091 ** Options:
1092 ** -L|--prefixlength N Set the length of the names of the DESTINATION
1093 ** subdirectories to N.
1094 */
1095 void test_hash_from_path_cmd(void) {
1096 char *zDest;
1097 char *zUuid;
1098 char *zFile;
1099 const char *zHashPolicy = "unknown";
1100 const char *zPrefixOpt = find_option("prefixlength","L",1);
1101 int iPrefixLength;
1102 if( !zPrefixOpt ){
1103 iPrefixLength = 2;
1104 }else{
1105 iPrefixLength = atoi(zPrefixOpt);
1106 if( iPrefixLength<0 || iPrefixLength>9 ){
1107 fossil_fatal("N(%s) is not a valid prefix length!",zPrefixOpt);
1108 }
1109 }
1110 if( g.argc!=4 ){
1111 usage ("?OPTIONS? DESTINATION UUID");
1112 }
1113 zDest = g.argv[2];
1114 zUuid = g.argv[3];
1115 if( iPrefixLength ){
1116 zFNameFormat = mprintf("%s/%%.%ds/%%s",zDest,iPrefixLength);
1117 }else{
1118 zFNameFormat = mprintf("%s/%%s",zDest);
1119 }
1120 cchFNamePrefix = strlen(zDest);
1121 zFile = mprintf(zFNameFormat /*works-like:"%s:%s"*/,
1122 zUuid, zUuid+iPrefixLength);
1123 recon_set_hash_policy(cchFNamePrefix,zFile);
1124 if( saved_eHashPolicy!=-1 ){
1125 zHashPolicy = hpolicy_name();
1126 }
1127 recon_restore_hash_policy();
1128 fossil_print(
1129 "\nPath Name: %s"
1130 "\nHash Policy: %s\n",
1131 zFile,zHashPolicy);
1132 free(zFile);
1133 free(zFNameFormat);
1134 zFNameFormat = 0;
1135 cchFNamePrefix = 0;
1136 }
1137 #endif
1138
1139 /*
1140 ** COMMAND: reconstruct*
1141 **
1142 ** Usage: %fossil reconstruct ?OPTIONS? FILENAME DIRECTORY
1143 **
1144 ** This command studies the artifacts (files) in DIRECTORY and
1145 ** reconstructs the fossil record from them. It places the new
1146 ** fossil repository in FILENAME. Subdirectories are read, files
1147 ** with leading '.' in the filename are ignored.
1148 **
1149 ** Options:
1150 ** -K|--keep-rid1 Read the filename of the artifact with
1151 ** RID=1 from the file .rid in DIRECTORY.
1152 **
1153 ** See also: deconstruct, rebuild
1154 */
1155 void reconstruct_cmd(void) {
1156 char *zPassword;
1157 fKeepRid1 = find_option("keep-rid1","K",0)!=0;
1158 if( g.argc!=4 ){
1159 usage("FILENAME DIRECTORY");
1160 }
1161 if( file_isdir(g.argv[3], ExtFILE)!=1 ){
1162 fossil_print("\"%s\" is not a directory\n\n", g.argv[3]);
@@ -1041,23 +1204,25 @@
1204 ** AABBBBBBBBB.. is the 40+ character artifact ID, AA the first 2 characters.
1205 ** If -L|--prefixlength is given, the length (default 2) of the directory
1206 ** prefix can be set to 0,1,..,9 characters.
1207 **
1208 ** Options:
1209 ** -R|--repository REPOSITORY Deconstruct given REPOSITORY.
1210 ** -K|--keep-rid1 Save the filename of the artifact with RID=1 to
1211 ** the file .rid1 in the DESTINATION directory.
1212 ** -L|--prefixlength N Set the length of the names of the DESTINATION
1213 ** subdirectories to N.
1214 ** --private Include private artifacts.
1215 **
1216 ** See also: rebuild, reconstruct
1217 */
1218 void deconstruct_cmd(void){
 
1219 const char *zPrefixOpt;
1220 Stmt s;
1221 int privateFlag;
1222
1223 fKeepRid1 = find_option("keep-rid1","K",0)!=0;
1224 /* get and check prefix length argument and build format string */
1225 zPrefixOpt=find_option("prefixlength","L",1);
1226 if( !zPrefixOpt ){
1227 prefixLength = 2;
1228 }else{
@@ -1092,10 +1257,11 @@
1257 if( prefixLength ){
1258 zFNameFormat = mprintf("%s/%%.%ds/%%s",zDestDir,prefixLength);
1259 }else{
1260 zFNameFormat = mprintf("%s/%%s",zDestDir);
1261 }
1262 cchFNamePrefix = strlen(zDestDir);
1263
1264 bag_init(&bagDone);
1265 ttyOutput = 1;
1266 processCnt = 0;
1267 if (!g.fQuiet) {
1268

Keyboard Shortcuts

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