Fossil SCM

Improvements to the "fossil import" command so that it can now (hopefully) interpret "breezy" files.

drh 2020-10-01 18:34 trunk merge
Commit d82534b3acd76e9d92f9f801666448c072fa2990842883f821d2b05aea92f0ff
1 file changed +45 -15
+45 -15
--- src/import.c
+++ src/import.c
@@ -68,10 +68,11 @@
6868
int nMergeAlloc; /* Number of slots in azMerge[] */
6969
char **azMerge; /* Merge values */
7070
int nFile; /* Number of aFile values */
7171
int nFileAlloc; /* Number of slots in aFile[] */
7272
ImportFile *aFile; /* Information about files in a commit */
73
+ ImportFile *pInlineFile; /* File marked "inline" */
7374
int fromLoaded; /* True zFrom content loaded into aFile[] */
7475
int tagCommit; /* True if the commit adds a tag */
7576
} gg;
7677
7778
/*
@@ -149,10 +150,11 @@
149150
** artifact hash in gg.zPrevCheckin.
150151
*/
151152
static int fast_insert_content(
152153
Blob *pContent, /* Content to insert */
153154
const char *zMark, /* Label using this mark, if not NULL */
155
+ ImportFile *pFile, /* Save hash on this file, if not NULL */
154156
int saveHash, /* Save artifact hash in gg.zPrevCheckin */
155157
int doParse /* Invoke manifest_crosslink() */
156158
){
157159
Blob hash;
158160
Blob cmpr;
@@ -193,26 +195,38 @@
193195
}
194196
if( saveHash ){
195197
fossil_free(gg.zPrevCheckin);
196198
gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
197199
}
200
+ if( pFile ){
201
+ fossil_free(pFile->zUuid);
202
+ pFile->zUuid = fossil_strdup(blob_str(&hash));
203
+ }
198204
blob_reset(&hash);
199205
return rid;
200206
}
207
+
208
+/*
209
+** Check to ensure the file in gg.aData,gg.nData is not a control
210
+** artifact. Then add the file to the repository.
211
+*/
212
+static void check_and_add_file(const char *zMark, ImportFile *pFile){
213
+ Blob content;
214
+ blob_init(&content, gg.aData, gg.nData);
215
+ if( gg.nData && manifest_is_well_formed(gg.aData, gg.nData) ){
216
+ sterilize_manifest(&content, -1);
217
+ }
218
+ fast_insert_content(&content, zMark, pFile, 0, 0);
219
+ blob_reset(&content);
220
+}
201221
202222
/*
203223
** Use data accumulated in gg from a "blob" record to add a new file
204224
** to the BLOB table.
205225
*/
206226
static void finish_blob(void){
207
- Blob content;
208
- blob_init(&content, gg.aData, gg.nData);
209
- if( manifest_is_well_formed(gg.aData, gg.nData) ){
210
- sterilize_manifest(&content, -1);
211
- }
212
- fast_insert_content(&content, gg.zMark, 0, 0);
213
- blob_reset(&content);
227
+ check_and_add_file(gg.zMark, 0);
214228
import_reset(0);
215229
}
216230
217231
/*
218232
** Use data accumulated in gg from a "tag" record to add a new
@@ -229,11 +243,11 @@
229243
blob_appendf(&record, " %F", gg.zComment);
230244
}
231245
blob_appendf(&record, "\nU %F\n", gg.zUser);
232246
md5sum_blob(&record, &cksum);
233247
blob_appendf(&record, "Z %b\n", &cksum);
234
- fast_insert_content(&record, 0, 0, 1);
248
+ fast_insert_content(&record, 0, 0, 0, 1);
235249
blob_reset(&cksum);
236250
blob_reset(&record);
237251
}
238252
import_reset(0);
239253
}
@@ -328,11 +342,11 @@
328342
db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
329343
gg.zMark, gg.zBranch);
330344
blob_appendf(&record, "U %F\n", gg.zUser);
331345
md5sum_blob(&record, &cksum);
332346
blob_appendf(&record, "Z %b\n", &cksum);
333
- fast_insert_content(&record, gg.zMark, 1, 1);
347
+ fast_insert_content(&record, gg.zMark, 0, 1, 1);
334348
blob_reset(&cksum);
335349
336350
/* The "git fast-export" command might output multiple "commit" lines
337351
** that reference a tag using "refs/tags/TAGNAME". The tag should only
338352
** be applied to the last commit that is output. The problem is we do not
@@ -627,10 +641,14 @@
627641
gg.zComment = gg.aData;
628642
gg.aData = 0;
629643
gg.nData = 0;
630644
}
631645
}
646
+ if( gg.pInlineFile ){
647
+ check_and_add_file(0, gg.pInlineFile);
648
+ gg.pInlineFile = 0;
649
+ }
632650
}else
633651
if( (!ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
634652
|| (ggit.authorFlag && strncmp(zLine, "committer ",10)==0
635653
&& gg.zUser!=NULL) ){
636654
/* No-op */
@@ -697,11 +715,16 @@
697715
pFile->zName = fossil_strdup(zName);
698716
}
699717
pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
700718
pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
701719
fossil_free(pFile->zUuid);
702
- pFile->zUuid = resolve_committish(zUuid);
720
+ if( strcmp(zUuid,"inline")==0 ){
721
+ pFile->zUuid = 0;
722
+ gg.pInlineFile = pFile;
723
+ }else{
724
+ pFile->zUuid = resolve_committish(zUuid);
725
+ }
703726
pFile->isFrom = 0;
704727
}else
705728
if( strncmp(zLine, "D ", 2)==0 ){
706729
import_prior_files();
707730
z = &zLine[2];
@@ -731,11 +754,11 @@
731754
pNew = import_add_file();
732755
pFile = &gg.aFile[i-1];
733756
if( strlen(pFile->zName)>nFrom ){
734757
pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
735758
}else{
736
- pNew->zName = fossil_strdup(pFile->zName);
759
+ pNew->zName = fossil_strdup(zTo);
737760
}
738761
pNew->isExe = pFile->isExe;
739762
pNew->isLink = pFile->isLink;
740763
pNew->zUuid = fossil_strdup(pFile->zUuid);
741764
pNew->isFrom = 0;
@@ -754,11 +777,11 @@
754777
pNew = import_add_file();
755778
pFile = &gg.aFile[i-1];
756779
if( strlen(pFile->zName)>nFrom ){
757780
pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
758781
}else{
759
- pNew->zName = fossil_strdup(pFile->zName);
782
+ pNew->zName = fossil_strdup(zTo);
760783
}
761784
pNew->zPrior = pFile->zName;
762785
pNew->isExe = pFile->isExe;
763786
pNew->isLink = pFile->isLink;
764787
pNew->zUuid = pFile->zUuid;
@@ -765,19 +788,26 @@
765788
pNew->isFrom = 0;
766789
gg.nFile--;
767790
*pFile = *pNew;
768791
memset(pNew, 0, sizeof(*pNew));
769792
}
770
- fossil_fatal("cannot handle R records, use --full-tree");
771793
}else
772794
if( strncmp(zLine, "deleteall", 9)==0 ){
773795
gg.fromLoaded = 1;
774796
}else
775797
if( strncmp(zLine, "N ", 2)==0 ){
776798
/* No-op */
777799
}else
778
-
800
+ if( strncmp(zLine, "property branch-nick ", 21)==0 ){
801
+ /* Breezy uses this property to store the branch name.
802
+ ** It has two values. Integer branch number, then the
803
+ ** user-readable branch name. */
804
+ z = &zLine[21];
805
+ next_token(&z);
806
+ fossil_free(gg.zBranch);
807
+ gg.zBranch = fossil_strdup(next_token(&z));
808
+ }else
779809
{
780810
goto malformed_line;
781811
}
782812
}
783813
gg.xFinish();
@@ -1876,11 +1906,11 @@
18761906
git_fast_import(pIn);
18771907
db_prepare(&q, "SELECT tcontent FROM xtag");
18781908
while( db_step(&q)==SQLITE_ROW ){
18791909
Blob record;
18801910
db_ephemeral_blob(&q, 0, &record);
1881
- fast_insert_content(&record, 0, 0, 1);
1911
+ fast_insert_content(&record, 0, 0, 0, 1);
18821912
import_reset(0);
18831913
}
18841914
db_finalize(&q);
18851915
if( markfile_out ){
18861916
int rid;
18871917
--- src/import.c
+++ src/import.c
@@ -68,10 +68,11 @@
68 int nMergeAlloc; /* Number of slots in azMerge[] */
69 char **azMerge; /* Merge values */
70 int nFile; /* Number of aFile values */
71 int nFileAlloc; /* Number of slots in aFile[] */
72 ImportFile *aFile; /* Information about files in a commit */
 
73 int fromLoaded; /* True zFrom content loaded into aFile[] */
74 int tagCommit; /* True if the commit adds a tag */
75 } gg;
76
77 /*
@@ -149,10 +150,11 @@
149 ** artifact hash in gg.zPrevCheckin.
150 */
151 static int fast_insert_content(
152 Blob *pContent, /* Content to insert */
153 const char *zMark, /* Label using this mark, if not NULL */
 
154 int saveHash, /* Save artifact hash in gg.zPrevCheckin */
155 int doParse /* Invoke manifest_crosslink() */
156 ){
157 Blob hash;
158 Blob cmpr;
@@ -193,26 +195,38 @@
193 }
194 if( saveHash ){
195 fossil_free(gg.zPrevCheckin);
196 gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
197 }
 
 
 
 
198 blob_reset(&hash);
199 return rid;
200 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
202 /*
203 ** Use data accumulated in gg from a "blob" record to add a new file
204 ** to the BLOB table.
205 */
206 static void finish_blob(void){
207 Blob content;
208 blob_init(&content, gg.aData, gg.nData);
209 if( manifest_is_well_formed(gg.aData, gg.nData) ){
210 sterilize_manifest(&content, -1);
211 }
212 fast_insert_content(&content, gg.zMark, 0, 0);
213 blob_reset(&content);
214 import_reset(0);
215 }
216
217 /*
218 ** Use data accumulated in gg from a "tag" record to add a new
@@ -229,11 +243,11 @@
229 blob_appendf(&record, " %F", gg.zComment);
230 }
231 blob_appendf(&record, "\nU %F\n", gg.zUser);
232 md5sum_blob(&record, &cksum);
233 blob_appendf(&record, "Z %b\n", &cksum);
234 fast_insert_content(&record, 0, 0, 1);
235 blob_reset(&cksum);
236 blob_reset(&record);
237 }
238 import_reset(0);
239 }
@@ -328,11 +342,11 @@
328 db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
329 gg.zMark, gg.zBranch);
330 blob_appendf(&record, "U %F\n", gg.zUser);
331 md5sum_blob(&record, &cksum);
332 blob_appendf(&record, "Z %b\n", &cksum);
333 fast_insert_content(&record, gg.zMark, 1, 1);
334 blob_reset(&cksum);
335
336 /* The "git fast-export" command might output multiple "commit" lines
337 ** that reference a tag using "refs/tags/TAGNAME". The tag should only
338 ** be applied to the last commit that is output. The problem is we do not
@@ -627,10 +641,14 @@
627 gg.zComment = gg.aData;
628 gg.aData = 0;
629 gg.nData = 0;
630 }
631 }
 
 
 
 
632 }else
633 if( (!ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
634 || (ggit.authorFlag && strncmp(zLine, "committer ",10)==0
635 && gg.zUser!=NULL) ){
636 /* No-op */
@@ -697,11 +715,16 @@
697 pFile->zName = fossil_strdup(zName);
698 }
699 pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
700 pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
701 fossil_free(pFile->zUuid);
702 pFile->zUuid = resolve_committish(zUuid);
 
 
 
 
 
703 pFile->isFrom = 0;
704 }else
705 if( strncmp(zLine, "D ", 2)==0 ){
706 import_prior_files();
707 z = &zLine[2];
@@ -731,11 +754,11 @@
731 pNew = import_add_file();
732 pFile = &gg.aFile[i-1];
733 if( strlen(pFile->zName)>nFrom ){
734 pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
735 }else{
736 pNew->zName = fossil_strdup(pFile->zName);
737 }
738 pNew->isExe = pFile->isExe;
739 pNew->isLink = pFile->isLink;
740 pNew->zUuid = fossil_strdup(pFile->zUuid);
741 pNew->isFrom = 0;
@@ -754,11 +777,11 @@
754 pNew = import_add_file();
755 pFile = &gg.aFile[i-1];
756 if( strlen(pFile->zName)>nFrom ){
757 pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
758 }else{
759 pNew->zName = fossil_strdup(pFile->zName);
760 }
761 pNew->zPrior = pFile->zName;
762 pNew->isExe = pFile->isExe;
763 pNew->isLink = pFile->isLink;
764 pNew->zUuid = pFile->zUuid;
@@ -765,19 +788,26 @@
765 pNew->isFrom = 0;
766 gg.nFile--;
767 *pFile = *pNew;
768 memset(pNew, 0, sizeof(*pNew));
769 }
770 fossil_fatal("cannot handle R records, use --full-tree");
771 }else
772 if( strncmp(zLine, "deleteall", 9)==0 ){
773 gg.fromLoaded = 1;
774 }else
775 if( strncmp(zLine, "N ", 2)==0 ){
776 /* No-op */
777 }else
778
 
 
 
 
 
 
 
 
779 {
780 goto malformed_line;
781 }
782 }
783 gg.xFinish();
@@ -1876,11 +1906,11 @@
1876 git_fast_import(pIn);
1877 db_prepare(&q, "SELECT tcontent FROM xtag");
1878 while( db_step(&q)==SQLITE_ROW ){
1879 Blob record;
1880 db_ephemeral_blob(&q, 0, &record);
1881 fast_insert_content(&record, 0, 0, 1);
1882 import_reset(0);
1883 }
1884 db_finalize(&q);
1885 if( markfile_out ){
1886 int rid;
1887
--- src/import.c
+++ src/import.c
@@ -68,10 +68,11 @@
68 int nMergeAlloc; /* Number of slots in azMerge[] */
69 char **azMerge; /* Merge values */
70 int nFile; /* Number of aFile values */
71 int nFileAlloc; /* Number of slots in aFile[] */
72 ImportFile *aFile; /* Information about files in a commit */
73 ImportFile *pInlineFile; /* File marked "inline" */
74 int fromLoaded; /* True zFrom content loaded into aFile[] */
75 int tagCommit; /* True if the commit adds a tag */
76 } gg;
77
78 /*
@@ -149,10 +150,11 @@
150 ** artifact hash in gg.zPrevCheckin.
151 */
152 static int fast_insert_content(
153 Blob *pContent, /* Content to insert */
154 const char *zMark, /* Label using this mark, if not NULL */
155 ImportFile *pFile, /* Save hash on this file, if not NULL */
156 int saveHash, /* Save artifact hash in gg.zPrevCheckin */
157 int doParse /* Invoke manifest_crosslink() */
158 ){
159 Blob hash;
160 Blob cmpr;
@@ -193,26 +195,38 @@
195 }
196 if( saveHash ){
197 fossil_free(gg.zPrevCheckin);
198 gg.zPrevCheckin = fossil_strdup(blob_str(&hash));
199 }
200 if( pFile ){
201 fossil_free(pFile->zUuid);
202 pFile->zUuid = fossil_strdup(blob_str(&hash));
203 }
204 blob_reset(&hash);
205 return rid;
206 }
207
208 /*
209 ** Check to ensure the file in gg.aData,gg.nData is not a control
210 ** artifact. Then add the file to the repository.
211 */
212 static void check_and_add_file(const char *zMark, ImportFile *pFile){
213 Blob content;
214 blob_init(&content, gg.aData, gg.nData);
215 if( gg.nData && manifest_is_well_formed(gg.aData, gg.nData) ){
216 sterilize_manifest(&content, -1);
217 }
218 fast_insert_content(&content, zMark, pFile, 0, 0);
219 blob_reset(&content);
220 }
221
222 /*
223 ** Use data accumulated in gg from a "blob" record to add a new file
224 ** to the BLOB table.
225 */
226 static void finish_blob(void){
227 check_and_add_file(gg.zMark, 0);
 
 
 
 
 
 
228 import_reset(0);
229 }
230
231 /*
232 ** Use data accumulated in gg from a "tag" record to add a new
@@ -229,11 +243,11 @@
243 blob_appendf(&record, " %F", gg.zComment);
244 }
245 blob_appendf(&record, "\nU %F\n", gg.zUser);
246 md5sum_blob(&record, &cksum);
247 blob_appendf(&record, "Z %b\n", &cksum);
248 fast_insert_content(&record, 0, 0, 0, 1);
249 blob_reset(&cksum);
250 blob_reset(&record);
251 }
252 import_reset(0);
253 }
@@ -328,11 +342,11 @@
342 db_multi_exec("INSERT INTO xbranch(tname, brnm) VALUES(%Q,%Q)",
343 gg.zMark, gg.zBranch);
344 blob_appendf(&record, "U %F\n", gg.zUser);
345 md5sum_blob(&record, &cksum);
346 blob_appendf(&record, "Z %b\n", &cksum);
347 fast_insert_content(&record, gg.zMark, 0, 1, 1);
348 blob_reset(&cksum);
349
350 /* The "git fast-export" command might output multiple "commit" lines
351 ** that reference a tag using "refs/tags/TAGNAME". The tag should only
352 ** be applied to the last commit that is output. The problem is we do not
@@ -627,10 +641,14 @@
641 gg.zComment = gg.aData;
642 gg.aData = 0;
643 gg.nData = 0;
644 }
645 }
646 if( gg.pInlineFile ){
647 check_and_add_file(0, gg.pInlineFile);
648 gg.pInlineFile = 0;
649 }
650 }else
651 if( (!ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
652 || (ggit.authorFlag && strncmp(zLine, "committer ",10)==0
653 && gg.zUser!=NULL) ){
654 /* No-op */
@@ -697,11 +715,16 @@
715 pFile->zName = fossil_strdup(zName);
716 }
717 pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
718 pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
719 fossil_free(pFile->zUuid);
720 if( strcmp(zUuid,"inline")==0 ){
721 pFile->zUuid = 0;
722 gg.pInlineFile = pFile;
723 }else{
724 pFile->zUuid = resolve_committish(zUuid);
725 }
726 pFile->isFrom = 0;
727 }else
728 if( strncmp(zLine, "D ", 2)==0 ){
729 import_prior_files();
730 z = &zLine[2];
@@ -731,11 +754,11 @@
754 pNew = import_add_file();
755 pFile = &gg.aFile[i-1];
756 if( strlen(pFile->zName)>nFrom ){
757 pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
758 }else{
759 pNew->zName = fossil_strdup(zTo);
760 }
761 pNew->isExe = pFile->isExe;
762 pNew->isLink = pFile->isLink;
763 pNew->zUuid = fossil_strdup(pFile->zUuid);
764 pNew->isFrom = 0;
@@ -754,11 +777,11 @@
777 pNew = import_add_file();
778 pFile = &gg.aFile[i-1];
779 if( strlen(pFile->zName)>nFrom ){
780 pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
781 }else{
782 pNew->zName = fossil_strdup(zTo);
783 }
784 pNew->zPrior = pFile->zName;
785 pNew->isExe = pFile->isExe;
786 pNew->isLink = pFile->isLink;
787 pNew->zUuid = pFile->zUuid;
@@ -765,19 +788,26 @@
788 pNew->isFrom = 0;
789 gg.nFile--;
790 *pFile = *pNew;
791 memset(pNew, 0, sizeof(*pNew));
792 }
 
793 }else
794 if( strncmp(zLine, "deleteall", 9)==0 ){
795 gg.fromLoaded = 1;
796 }else
797 if( strncmp(zLine, "N ", 2)==0 ){
798 /* No-op */
799 }else
800 if( strncmp(zLine, "property branch-nick ", 21)==0 ){
801 /* Breezy uses this property to store the branch name.
802 ** It has two values. Integer branch number, then the
803 ** user-readable branch name. */
804 z = &zLine[21];
805 next_token(&z);
806 fossil_free(gg.zBranch);
807 gg.zBranch = fossil_strdup(next_token(&z));
808 }else
809 {
810 goto malformed_line;
811 }
812 }
813 gg.xFinish();
@@ -1876,11 +1906,11 @@
1906 git_fast_import(pIn);
1907 db_prepare(&q, "SELECT tcontent FROM xtag");
1908 while( db_step(&q)==SQLITE_ROW ){
1909 Blob record;
1910 db_ephemeral_blob(&q, 0, &record);
1911 fast_insert_content(&record, 0, 0, 0, 1);
1912 import_reset(0);
1913 }
1914 db_finalize(&q);
1915 if( markfile_out ){
1916 int rid;
1917

Keyboard Shortcuts

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