Fossil SCM
Complete the parts of the "fossil unversioned" command used to add and remove content.
Commit
fb3c81d8ba0f632ad05fd59c7e8089ae745ed8b8
Parent
7c176f7aebb11bc…
1 file changed
+146
-42
+146
-42
| --- src/unversioned.c | ||
| +++ src/unversioned.c | ||
| @@ -48,10 +48,41 @@ | ||
| 48 | 48 | void unversioned_schema(void){ |
| 49 | 49 | if( !db_table_exists("repository", "unversioned") ){ |
| 50 | 50 | db_multi_exec(zUnversionedInit /*works-like:"%w"*/, db_name("repository")); |
| 51 | 51 | } |
| 52 | 52 | } |
| 53 | + | |
| 54 | +/* | |
| 55 | +** Return a string which is the hash of the unversioned content. | |
| 56 | +** This is the hash used by repositories to compare content before | |
| 57 | +** exchanging a catalog. So all repositories must compute this hash | |
| 58 | +** in exactly the same way. | |
| 59 | +** | |
| 60 | +** If debugFlag is set, force the value to be recomputed and write | |
| 61 | +** the text of the hashed string to stdout. | |
| 62 | +*/ | |
| 63 | +const char *unversioned_content_hash(int debugFlag){ | |
| 64 | + const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0); | |
| 65 | + if( zHash==0 ){ | |
| 66 | + Stmt q; | |
| 67 | + db_prepare(&q, | |
| 68 | + "SELECT printf('%%s %%s %%s\n',name,datetime(mtime,'unixepoch'),hash)" | |
| 69 | + " FROM unversioned" | |
| 70 | + " WHERE hash IS NOT NULL" | |
| 71 | + " ORDER BY name" | |
| 72 | + ); | |
| 73 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 74 | + const char *z = db_column_text(&q, 0); | |
| 75 | + if( debugFlag ) fossil_print("%s", z); | |
| 76 | + sha1sum_step_text(z,-1); | |
| 77 | + } | |
| 78 | + db_finalize(&q); | |
| 79 | + db_set("uv-hash", sha1sum_finish(0), 0); | |
| 80 | + zHash = db_get("uv-hash",0); | |
| 81 | + } | |
| 82 | + return zHash; | |
| 83 | +} | |
| 53 | 84 | |
| 54 | 85 | /* |
| 55 | 86 | ** COMMAND: unversioned |
| 56 | 87 | ** |
| 57 | 88 | ** Usage: %fossil unversioned SUBCOMMAND ARGS... |
| @@ -61,18 +92,20 @@ | ||
| 61 | 92 | ** of each UV-file is retained. Changes to an UV-file are permanent and cannot |
| 62 | 93 | ** be undone, so use appropriate caution with this command. |
| 63 | 94 | ** |
| 64 | 95 | ** Subcommands: |
| 65 | 96 | ** |
| 66 | -** add FILE ?INPUT? Add or update an unversioned file FILE in the local | |
| 67 | -** repository so that it matches the INPUT file on disk. | |
| 68 | -** Content is read from stdin if INPUT is "-" or omitted. | |
| 97 | +** add FILE ... Add or update an unversioned files in the local | |
| 98 | +** repository so that it matches FILE on disk. | |
| 99 | +** Use "--as UVFILE" to give the file a different name | |
| 100 | +** in the repository than what it called on disk. | |
| 69 | 101 | ** Changes are not pushed to other repositories until |
| 70 | 102 | ** the next sync. |
| 71 | 103 | ** |
| 72 | -** cat FILE ?OUTFILE? Write the content of unversioned file FILE to OUTFILE | |
| 73 | -** on disk, or to stdout if OUTFILE is "-" or is omitted. | |
| 104 | +** cat FILE ... Concatenate the content of FILEs to stdout. | |
| 105 | +** | |
| 106 | +** export FILE OUTPUT Write the content of FILE into OUTPUT on disk | |
| 74 | 107 | ** |
| 75 | 108 | ** list | ls Show all unversioned files held in the local repository. |
| 76 | 109 | ** |
| 77 | 110 | ** revert ?URL? Restore the state of all unversioned files in the local |
| 78 | 111 | ** repository to match the remote repository URL. |
| @@ -104,69 +137,140 @@ | ||
| 104 | 137 | }else{ |
| 105 | 138 | mtime = db_int(0, "SELECT strftime('%%s',%Q)", zMtime); |
| 106 | 139 | if( mtime<=0 ) fossil_fatal("bad timestamp: %Q", zMtime); |
| 107 | 140 | } |
| 108 | 141 | if( memcmp(zCmd, "add", nCmd)==0 ){ |
| 109 | - const char *zFile; | |
| 110 | 142 | const char *zIn; |
| 143 | + const char *zAs; | |
| 111 | 144 | Blob file; |
| 112 | 145 | Blob hash; |
| 113 | 146 | Blob compressed; |
| 114 | 147 | Stmt ins; |
| 115 | - if( g.argc!=4 && g.argc!=5 ) usage("add FILE ?INPUT?"); | |
| 116 | - zFile = g.argv[3]; | |
| 117 | - if( !file_is_simple_pathname(zFile,1) ){ | |
| 118 | - fossil_fatal("'%Q' is not an acceptable filename", zFile); | |
| 119 | - } | |
| 120 | - zIn = g.argc==5 ? g.argv[4] : "-"; | |
| 121 | - blob_init(&file,0,0); | |
| 122 | - blob_read_from_file(&file, zIn); | |
| 123 | - sha1sum_blob(&file, &hash); | |
| 124 | - blob_compress(&file, &compressed); | |
| 148 | + int i; | |
| 149 | + | |
| 150 | + zAs = find_option("as",0,1); | |
| 151 | + if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); | |
| 152 | + verify_all_options(); | |
| 125 | 153 | db_begin_transaction(); |
| 126 | 154 | content_rcvid_init(); |
| 127 | 155 | db_prepare(&ins, |
| 128 | 156 | "REPLACE INTO unversioned(name,rcvid,mtime,hash,sz,content)" |
| 129 | 157 | " VALUES(:name,:rcvid,:mtime,:hash,:sz,:content)" |
| 130 | 158 | ); |
| 131 | - db_bind_text(&ins, ":name", zFile); | |
| 132 | - db_bind_int(&ins, ":rcvid", g.rcvid); | |
| 133 | - db_bind_int64(&ins, ":mtime", mtime); | |
| 134 | - db_bind_text(&ins, ":hash", blob_str(&hash)); | |
| 135 | - db_bind_int(&ins, ":sz", blob_size(&file)); | |
| 136 | - db_bind_blob(&ins, ":content", &compressed); | |
| 137 | - db_step(&ins); | |
| 159 | + for(i=3; i<g.argc; i++){ | |
| 160 | + zIn = zAs ? zAs : g.argv[i]; | |
| 161 | + if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){ | |
| 162 | + fossil_fatal("'%Q' is not an acceptable filename", zIn); | |
| 163 | + } | |
| 164 | + blob_init(&file,0,0); | |
| 165 | + blob_read_from_file(&file, g.argv[i]); | |
| 166 | + sha1sum_blob(&file, &hash); | |
| 167 | + blob_compress(&file, &compressed); | |
| 168 | + db_bind_text(&ins, ":name", zIn); | |
| 169 | + db_bind_int(&ins, ":rcvid", g.rcvid); | |
| 170 | + db_bind_int64(&ins, ":mtime", mtime); | |
| 171 | + db_bind_text(&ins, ":hash", blob_str(&hash)); | |
| 172 | + db_bind_int(&ins, ":sz", blob_size(&file)); | |
| 173 | + db_bind_blob(&ins, ":content", &compressed); | |
| 174 | + db_step(&ins); | |
| 175 | + db_reset(&ins); | |
| 176 | + blob_reset(&compressed); | |
| 177 | + blob_reset(&hash); | |
| 178 | + blob_reset(&file); | |
| 179 | + } | |
| 138 | 180 | db_finalize(&ins); |
| 139 | - blob_reset(&compressed); | |
| 140 | - blob_reset(&hash); | |
| 141 | - blob_reset(&file); | |
| 142 | - /* Clear the uvhash cache */ | |
| 181 | + db_unset("uv-hash", 0); | |
| 143 | 182 | db_end_transaction(0); |
| 144 | 183 | }else if( memcmp(zCmd, "cat", nCmd)==0 ){ |
| 184 | + int i; | |
| 185 | + verify_all_options(); | |
| 186 | + db_begin_transaction(); | |
| 187 | + for(i=3; i<g.argc; i++){ | |
| 188 | + Blob content; | |
| 189 | + blob_init(&content, 0, 0); | |
| 190 | + db_blob(&content, "SELECT content FROM unversioned WHERE name=%Q",g.argv[i]); | |
| 191 | + if( blob_size(&content)==0 ){ | |
| 192 | + fossil_fatal("no such uv-file: %Q", g.argv[i]); | |
| 193 | + } | |
| 194 | + blob_uncompress(&content, &content); | |
| 195 | + blob_write_to_file(&content, "-"); | |
| 196 | + blob_reset(&content); | |
| 197 | + } | |
| 198 | + db_end_transaction(0); | |
| 199 | + }else if( memcmp(zCmd, "export", nCmd)==0 ){ | |
| 200 | + Blob content; | |
| 201 | + verify_all_options(); | |
| 202 | + if( g.argc!=5 ) usage("export UVFILE OUTPUT"); | |
| 203 | + blob_init(&content, 0, 0); | |
| 204 | + db_blob(&content, "SELECT content FROM unversioned WHERE name=%Q", g.argv[3]); | |
| 205 | + if( blob_size(&content)==0 ){ | |
| 206 | + fossil_fatal("no such uv-file: %Q", g.argv[3]); | |
| 207 | + } | |
| 208 | + blob_uncompress(&content, &content); | |
| 209 | + blob_write_to_file(&content, g.argv[4]); | |
| 210 | + blob_reset(&content); | |
| 211 | + }else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */ | |
| 212 | + /* Show the hash value used during uv sync */ | |
| 213 | + int debugFlag = find_option("debug",0,0)!=0; | |
| 214 | + fossil_print("%s\n", unversioned_content_hash(debugFlag)); | |
| 145 | 215 | }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){ |
| 146 | 216 | Stmt q; |
| 147 | - db_prepare(&q, | |
| 148 | - "SELECT hash, datetime(mtime,'unixepoch'), sz, name, content IS NULL" | |
| 149 | - " FROM unversioned" | |
| 150 | - " WHERE hash IS NOT NULL" | |
| 151 | - " ORDER BY name;" | |
| 152 | - ); | |
| 153 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 154 | - fossil_print("%12.12s %s %8d %s%s\n", | |
| 155 | - db_column_text(&q,0), | |
| 156 | - db_column_text(&q,1), | |
| 157 | - db_column_int(&q,2), | |
| 158 | - db_column_text(&q,3), | |
| 159 | - db_column_int(&q,4) ? " ** no content ** ": "" | |
| 160 | - ); | |
| 217 | + int allFlag = find_option("all","a",0)!=0; | |
| 218 | + int longFlag = find_option("l",0,0)!=0 || (nCmd>1 && zCmd[1]=='i'); | |
| 219 | + verify_all_options(); | |
| 220 | + if( !longFlag ){ | |
| 221 | + if( allFlag ){ | |
| 222 | + db_prepare(&q, "SELECT name FROM unversioned ORDER BY name"); | |
| 223 | + }else{ | |
| 224 | + db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL" | |
| 225 | + " ORDER BY name"); | |
| 226 | + } | |
| 227 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 228 | + fossil_print("%s\n", db_column_text(&q,0)); | |
| 229 | + } | |
| 230 | + }else{ | |
| 231 | + db_prepare(&q, | |
| 232 | + "SELECT hash, datetime(mtime,'unixepoch'), sz, name, content IS NULL" | |
| 233 | + " FROM unversioned" | |
| 234 | + " ORDER BY name;" | |
| 235 | + ); | |
| 236 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 237 | + const char *zHash = db_column_text(&q, 0); | |
| 238 | + const char *zNoContent = ""; | |
| 239 | + if( zHash==0 ){ | |
| 240 | + if( !allFlag ) continue; | |
| 241 | + zHash = "(deleted)"; | |
| 242 | + }else if( db_column_int(&q,4) ){ | |
| 243 | + zNoContent = " (no content)"; | |
| 244 | + } | |
| 245 | + fossil_print("%12.12s %s %8d %s%s\n", | |
| 246 | + zHash, | |
| 247 | + db_column_text(&q,1), | |
| 248 | + db_column_int(&q,2), | |
| 249 | + db_column_text(&q,3), | |
| 250 | + zNoContent | |
| 251 | + ); | |
| 252 | + } | |
| 161 | 253 | } |
| 162 | 254 | db_finalize(&q); |
| 163 | 255 | }else if( memcmp(zCmd, "revert", nCmd)==0 || memcmp(zCmd,"sync",nCmd)==0 ){ |
| 164 | 256 | fossil_fatal("not yet implemented..."); |
| 165 | 257 | }else if( memcmp(zCmd, "rm", nCmd)==0 ){ |
| 258 | + int i; | |
| 259 | + verify_all_options(); | |
| 260 | + db_begin_transaction(); | |
| 261 | + for(i=3; i<g.argc; i++){ | |
| 262 | + db_multi_exec( | |
| 263 | + "UPDATE unversioned" | |
| 264 | + " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name=%Q", | |
| 265 | + mtime, g.argv[i] | |
| 266 | + ); | |
| 267 | + } | |
| 268 | + db_unset("uv-hash", 0); | |
| 269 | + db_end_transaction(0); | |
| 166 | 270 | }else{ |
| 167 | - usage("add|cat|ls|revert|rm|sync"); | |
| 271 | + usage("add|cat|export|ls|revert|rm|sync"); | |
| 168 | 272 | } |
| 169 | 273 | } |
| 170 | 274 | |
| 171 | 275 | #if 0 |
| 172 | 276 | *************************************************************************** |
| 173 | 277 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -48,10 +48,41 @@ | |
| 48 | void unversioned_schema(void){ |
| 49 | if( !db_table_exists("repository", "unversioned") ){ |
| 50 | db_multi_exec(zUnversionedInit /*works-like:"%w"*/, db_name("repository")); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | /* |
| 55 | ** COMMAND: unversioned |
| 56 | ** |
| 57 | ** Usage: %fossil unversioned SUBCOMMAND ARGS... |
| @@ -61,18 +92,20 @@ | |
| 61 | ** of each UV-file is retained. Changes to an UV-file are permanent and cannot |
| 62 | ** be undone, so use appropriate caution with this command. |
| 63 | ** |
| 64 | ** Subcommands: |
| 65 | ** |
| 66 | ** add FILE ?INPUT? Add or update an unversioned file FILE in the local |
| 67 | ** repository so that it matches the INPUT file on disk. |
| 68 | ** Content is read from stdin if INPUT is "-" or omitted. |
| 69 | ** Changes are not pushed to other repositories until |
| 70 | ** the next sync. |
| 71 | ** |
| 72 | ** cat FILE ?OUTFILE? Write the content of unversioned file FILE to OUTFILE |
| 73 | ** on disk, or to stdout if OUTFILE is "-" or is omitted. |
| 74 | ** |
| 75 | ** list | ls Show all unversioned files held in the local repository. |
| 76 | ** |
| 77 | ** revert ?URL? Restore the state of all unversioned files in the local |
| 78 | ** repository to match the remote repository URL. |
| @@ -104,69 +137,140 @@ | |
| 104 | }else{ |
| 105 | mtime = db_int(0, "SELECT strftime('%%s',%Q)", zMtime); |
| 106 | if( mtime<=0 ) fossil_fatal("bad timestamp: %Q", zMtime); |
| 107 | } |
| 108 | if( memcmp(zCmd, "add", nCmd)==0 ){ |
| 109 | const char *zFile; |
| 110 | const char *zIn; |
| 111 | Blob file; |
| 112 | Blob hash; |
| 113 | Blob compressed; |
| 114 | Stmt ins; |
| 115 | if( g.argc!=4 && g.argc!=5 ) usage("add FILE ?INPUT?"); |
| 116 | zFile = g.argv[3]; |
| 117 | if( !file_is_simple_pathname(zFile,1) ){ |
| 118 | fossil_fatal("'%Q' is not an acceptable filename", zFile); |
| 119 | } |
| 120 | zIn = g.argc==5 ? g.argv[4] : "-"; |
| 121 | blob_init(&file,0,0); |
| 122 | blob_read_from_file(&file, zIn); |
| 123 | sha1sum_blob(&file, &hash); |
| 124 | blob_compress(&file, &compressed); |
| 125 | db_begin_transaction(); |
| 126 | content_rcvid_init(); |
| 127 | db_prepare(&ins, |
| 128 | "REPLACE INTO unversioned(name,rcvid,mtime,hash,sz,content)" |
| 129 | " VALUES(:name,:rcvid,:mtime,:hash,:sz,:content)" |
| 130 | ); |
| 131 | db_bind_text(&ins, ":name", zFile); |
| 132 | db_bind_int(&ins, ":rcvid", g.rcvid); |
| 133 | db_bind_int64(&ins, ":mtime", mtime); |
| 134 | db_bind_text(&ins, ":hash", blob_str(&hash)); |
| 135 | db_bind_int(&ins, ":sz", blob_size(&file)); |
| 136 | db_bind_blob(&ins, ":content", &compressed); |
| 137 | db_step(&ins); |
| 138 | db_finalize(&ins); |
| 139 | blob_reset(&compressed); |
| 140 | blob_reset(&hash); |
| 141 | blob_reset(&file); |
| 142 | /* Clear the uvhash cache */ |
| 143 | db_end_transaction(0); |
| 144 | }else if( memcmp(zCmd, "cat", nCmd)==0 ){ |
| 145 | }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){ |
| 146 | Stmt q; |
| 147 | db_prepare(&q, |
| 148 | "SELECT hash, datetime(mtime,'unixepoch'), sz, name, content IS NULL" |
| 149 | " FROM unversioned" |
| 150 | " WHERE hash IS NOT NULL" |
| 151 | " ORDER BY name;" |
| 152 | ); |
| 153 | while( db_step(&q)==SQLITE_ROW ){ |
| 154 | fossil_print("%12.12s %s %8d %s%s\n", |
| 155 | db_column_text(&q,0), |
| 156 | db_column_text(&q,1), |
| 157 | db_column_int(&q,2), |
| 158 | db_column_text(&q,3), |
| 159 | db_column_int(&q,4) ? " ** no content ** ": "" |
| 160 | ); |
| 161 | } |
| 162 | db_finalize(&q); |
| 163 | }else if( memcmp(zCmd, "revert", nCmd)==0 || memcmp(zCmd,"sync",nCmd)==0 ){ |
| 164 | fossil_fatal("not yet implemented..."); |
| 165 | }else if( memcmp(zCmd, "rm", nCmd)==0 ){ |
| 166 | }else{ |
| 167 | usage("add|cat|ls|revert|rm|sync"); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | #if 0 |
| 172 | *************************************************************************** |
| 173 |
| --- src/unversioned.c | |
| +++ src/unversioned.c | |
| @@ -48,10 +48,41 @@ | |
| 48 | void unversioned_schema(void){ |
| 49 | if( !db_table_exists("repository", "unversioned") ){ |
| 50 | db_multi_exec(zUnversionedInit /*works-like:"%w"*/, db_name("repository")); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | /* |
| 55 | ** Return a string which is the hash of the unversioned content. |
| 56 | ** This is the hash used by repositories to compare content before |
| 57 | ** exchanging a catalog. So all repositories must compute this hash |
| 58 | ** in exactly the same way. |
| 59 | ** |
| 60 | ** If debugFlag is set, force the value to be recomputed and write |
| 61 | ** the text of the hashed string to stdout. |
| 62 | */ |
| 63 | const char *unversioned_content_hash(int debugFlag){ |
| 64 | const char *zHash = debugFlag ? 0 : db_get("uv-hash", 0); |
| 65 | if( zHash==0 ){ |
| 66 | Stmt q; |
| 67 | db_prepare(&q, |
| 68 | "SELECT printf('%%s %%s %%s\n',name,datetime(mtime,'unixepoch'),hash)" |
| 69 | " FROM unversioned" |
| 70 | " WHERE hash IS NOT NULL" |
| 71 | " ORDER BY name" |
| 72 | ); |
| 73 | while( db_step(&q)==SQLITE_ROW ){ |
| 74 | const char *z = db_column_text(&q, 0); |
| 75 | if( debugFlag ) fossil_print("%s", z); |
| 76 | sha1sum_step_text(z,-1); |
| 77 | } |
| 78 | db_finalize(&q); |
| 79 | db_set("uv-hash", sha1sum_finish(0), 0); |
| 80 | zHash = db_get("uv-hash",0); |
| 81 | } |
| 82 | return zHash; |
| 83 | } |
| 84 | |
| 85 | /* |
| 86 | ** COMMAND: unversioned |
| 87 | ** |
| 88 | ** Usage: %fossil unversioned SUBCOMMAND ARGS... |
| @@ -61,18 +92,20 @@ | |
| 92 | ** of each UV-file is retained. Changes to an UV-file are permanent and cannot |
| 93 | ** be undone, so use appropriate caution with this command. |
| 94 | ** |
| 95 | ** Subcommands: |
| 96 | ** |
| 97 | ** add FILE ... Add or update an unversioned files in the local |
| 98 | ** repository so that it matches FILE on disk. |
| 99 | ** Use "--as UVFILE" to give the file a different name |
| 100 | ** in the repository than what it called on disk. |
| 101 | ** Changes are not pushed to other repositories until |
| 102 | ** the next sync. |
| 103 | ** |
| 104 | ** cat FILE ... Concatenate the content of FILEs to stdout. |
| 105 | ** |
| 106 | ** export FILE OUTPUT Write the content of FILE into OUTPUT on disk |
| 107 | ** |
| 108 | ** list | ls Show all unversioned files held in the local repository. |
| 109 | ** |
| 110 | ** revert ?URL? Restore the state of all unversioned files in the local |
| 111 | ** repository to match the remote repository URL. |
| @@ -104,69 +137,140 @@ | |
| 137 | }else{ |
| 138 | mtime = db_int(0, "SELECT strftime('%%s',%Q)", zMtime); |
| 139 | if( mtime<=0 ) fossil_fatal("bad timestamp: %Q", zMtime); |
| 140 | } |
| 141 | if( memcmp(zCmd, "add", nCmd)==0 ){ |
| 142 | const char *zIn; |
| 143 | const char *zAs; |
| 144 | Blob file; |
| 145 | Blob hash; |
| 146 | Blob compressed; |
| 147 | Stmt ins; |
| 148 | int i; |
| 149 | |
| 150 | zAs = find_option("as",0,1); |
| 151 | if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE"); |
| 152 | verify_all_options(); |
| 153 | db_begin_transaction(); |
| 154 | content_rcvid_init(); |
| 155 | db_prepare(&ins, |
| 156 | "REPLACE INTO unversioned(name,rcvid,mtime,hash,sz,content)" |
| 157 | " VALUES(:name,:rcvid,:mtime,:hash,:sz,:content)" |
| 158 | ); |
| 159 | for(i=3; i<g.argc; i++){ |
| 160 | zIn = zAs ? zAs : g.argv[i]; |
| 161 | if( zIn[0]==0 || zIn[0]=='/' || !file_is_simple_pathname(zIn,1) ){ |
| 162 | fossil_fatal("'%Q' is not an acceptable filename", zIn); |
| 163 | } |
| 164 | blob_init(&file,0,0); |
| 165 | blob_read_from_file(&file, g.argv[i]); |
| 166 | sha1sum_blob(&file, &hash); |
| 167 | blob_compress(&file, &compressed); |
| 168 | db_bind_text(&ins, ":name", zIn); |
| 169 | db_bind_int(&ins, ":rcvid", g.rcvid); |
| 170 | db_bind_int64(&ins, ":mtime", mtime); |
| 171 | db_bind_text(&ins, ":hash", blob_str(&hash)); |
| 172 | db_bind_int(&ins, ":sz", blob_size(&file)); |
| 173 | db_bind_blob(&ins, ":content", &compressed); |
| 174 | db_step(&ins); |
| 175 | db_reset(&ins); |
| 176 | blob_reset(&compressed); |
| 177 | blob_reset(&hash); |
| 178 | blob_reset(&file); |
| 179 | } |
| 180 | db_finalize(&ins); |
| 181 | db_unset("uv-hash", 0); |
| 182 | db_end_transaction(0); |
| 183 | }else if( memcmp(zCmd, "cat", nCmd)==0 ){ |
| 184 | int i; |
| 185 | verify_all_options(); |
| 186 | db_begin_transaction(); |
| 187 | for(i=3; i<g.argc; i++){ |
| 188 | Blob content; |
| 189 | blob_init(&content, 0, 0); |
| 190 | db_blob(&content, "SELECT content FROM unversioned WHERE name=%Q",g.argv[i]); |
| 191 | if( blob_size(&content)==0 ){ |
| 192 | fossil_fatal("no such uv-file: %Q", g.argv[i]); |
| 193 | } |
| 194 | blob_uncompress(&content, &content); |
| 195 | blob_write_to_file(&content, "-"); |
| 196 | blob_reset(&content); |
| 197 | } |
| 198 | db_end_transaction(0); |
| 199 | }else if( memcmp(zCmd, "export", nCmd)==0 ){ |
| 200 | Blob content; |
| 201 | verify_all_options(); |
| 202 | if( g.argc!=5 ) usage("export UVFILE OUTPUT"); |
| 203 | blob_init(&content, 0, 0); |
| 204 | db_blob(&content, "SELECT content FROM unversioned WHERE name=%Q", g.argv[3]); |
| 205 | if( blob_size(&content)==0 ){ |
| 206 | fossil_fatal("no such uv-file: %Q", g.argv[3]); |
| 207 | } |
| 208 | blob_uncompress(&content, &content); |
| 209 | blob_write_to_file(&content, g.argv[4]); |
| 210 | blob_reset(&content); |
| 211 | }else if( memcmp(zCmd, "hash", nCmd)==0 ){ /* undocumented */ |
| 212 | /* Show the hash value used during uv sync */ |
| 213 | int debugFlag = find_option("debug",0,0)!=0; |
| 214 | fossil_print("%s\n", unversioned_content_hash(debugFlag)); |
| 215 | }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){ |
| 216 | Stmt q; |
| 217 | int allFlag = find_option("all","a",0)!=0; |
| 218 | int longFlag = find_option("l",0,0)!=0 || (nCmd>1 && zCmd[1]=='i'); |
| 219 | verify_all_options(); |
| 220 | if( !longFlag ){ |
| 221 | if( allFlag ){ |
| 222 | db_prepare(&q, "SELECT name FROM unversioned ORDER BY name"); |
| 223 | }else{ |
| 224 | db_prepare(&q, "SELECT name FROM unversioned WHERE hash IS NOT NULL" |
| 225 | " ORDER BY name"); |
| 226 | } |
| 227 | while( db_step(&q)==SQLITE_ROW ){ |
| 228 | fossil_print("%s\n", db_column_text(&q,0)); |
| 229 | } |
| 230 | }else{ |
| 231 | db_prepare(&q, |
| 232 | "SELECT hash, datetime(mtime,'unixepoch'), sz, name, content IS NULL" |
| 233 | " FROM unversioned" |
| 234 | " ORDER BY name;" |
| 235 | ); |
| 236 | while( db_step(&q)==SQLITE_ROW ){ |
| 237 | const char *zHash = db_column_text(&q, 0); |
| 238 | const char *zNoContent = ""; |
| 239 | if( zHash==0 ){ |
| 240 | if( !allFlag ) continue; |
| 241 | zHash = "(deleted)"; |
| 242 | }else if( db_column_int(&q,4) ){ |
| 243 | zNoContent = " (no content)"; |
| 244 | } |
| 245 | fossil_print("%12.12s %s %8d %s%s\n", |
| 246 | zHash, |
| 247 | db_column_text(&q,1), |
| 248 | db_column_int(&q,2), |
| 249 | db_column_text(&q,3), |
| 250 | zNoContent |
| 251 | ); |
| 252 | } |
| 253 | } |
| 254 | db_finalize(&q); |
| 255 | }else if( memcmp(zCmd, "revert", nCmd)==0 || memcmp(zCmd,"sync",nCmd)==0 ){ |
| 256 | fossil_fatal("not yet implemented..."); |
| 257 | }else if( memcmp(zCmd, "rm", nCmd)==0 ){ |
| 258 | int i; |
| 259 | verify_all_options(); |
| 260 | db_begin_transaction(); |
| 261 | for(i=3; i<g.argc; i++){ |
| 262 | db_multi_exec( |
| 263 | "UPDATE unversioned" |
| 264 | " SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name=%Q", |
| 265 | mtime, g.argv[i] |
| 266 | ); |
| 267 | } |
| 268 | db_unset("uv-hash", 0); |
| 269 | db_end_transaction(0); |
| 270 | }else{ |
| 271 | usage("add|cat|export|ls|revert|rm|sync"); |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | #if 0 |
| 276 | *************************************************************************** |
| 277 |