Fossil SCM
Added file size info to /json/dir (but only when checkin=... is specified) and /json/finfo. Changed /json/dir to not show uuid for dir entries because the associated UUID actually refers to a file in that dir.
Commit
7b89c7b5b3e1ec6572a901955f92722a5cc42231
Parent
4dae79503fc61e4…
2 files changed
+37
-16
+22
-28
+37
-16
| --- src/json_dir.c | ||
| +++ src/json_dir.c | ||
| @@ -50,10 +50,11 @@ | ||
| 50 | 50 | static cson_value * json_page_dir_list(){ |
| 51 | 51 | cson_object * zPayload = NULL; |
| 52 | 52 | cson_array * zEntries = NULL; |
| 53 | 53 | cson_object * zEntry = NULL; |
| 54 | 54 | cson_string * zKeyName = NULL; |
| 55 | + cson_string * zKeySize = NULL; | |
| 55 | 56 | cson_string * zKeyIsDir = NULL; |
| 56 | 57 | cson_string * zKeyUuid = NULL; |
| 57 | 58 | char * zD = NULL; |
| 58 | 59 | char const * zDX = NULL; |
| 59 | 60 | cson_value const * zDV = NULL; |
| @@ -105,11 +106,11 @@ | ||
| 105 | 106 | ** Subdirectory names begin with "/". This causes them to sort |
| 106 | 107 | ** first and it also gives us an easy way to distinguish files |
| 107 | 108 | ** from directories in the loop that follows. |
| 108 | 109 | */ |
| 109 | 110 | db_multi_exec( |
| 110 | - "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u);", | |
| 111 | + "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u, sz);", | |
| 111 | 112 | filename_collation() |
| 112 | 113 | ); |
| 113 | 114 | |
| 114 | 115 | if( zCI ){ |
| 115 | 116 | Stmt ins; |
| @@ -117,11 +118,13 @@ | ||
| 117 | 118 | ManifestFile *pPrev = 0; |
| 118 | 119 | int nPrev = 0; |
| 119 | 120 | int c; |
| 120 | 121 | |
| 121 | 122 | db_prepare(&ins, |
| 122 | - "INSERT OR IGNORE INTO localfiles VALUES(pathelement(:x,0), :u)" | |
| 123 | + "INSERT OR IGNORE INTO localfiles VALUES(pathelement(:x,0), :u, " | |
| 124 | + "(SELECT size from blob where uuid=:s)" | |
| 125 | + ")" | |
| 123 | 126 | ); |
| 124 | 127 | manifest_file_rewind(pM); |
| 125 | 128 | while( (pFile = manifest_file_next(pM,0))!=0 ){ |
| 126 | 129 | if( nD>0 |
| 127 | 130 | && ((pFile->zName[nD-1]!='/') || (0!=memcmp(pFile->zName, zD, nD-1))) |
| @@ -135,10 +138,11 @@ | ||
| 135 | 138 | ){ |
| 136 | 139 | continue; |
| 137 | 140 | } |
| 138 | 141 | db_bind_text(&ins, ":x", &pFile->zName[nD]); |
| 139 | 142 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 143 | + db_bind_text(&ins, ":s", pFile->zUuid); | |
| 140 | 144 | db_step(&ins); |
| 141 | 145 | db_reset(&ins); |
| 142 | 146 | pPrev = pFile; |
| 143 | 147 | for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} |
| 144 | 148 | if( c=='/' ) nPrev++; |
| @@ -146,11 +150,11 @@ | ||
| 146 | 150 | db_finalize(&ins); |
| 147 | 151 | }else if( zD && *zD ){ |
| 148 | 152 | if( filenames_are_case_sensitive() ){ |
| 149 | 153 | db_multi_exec( |
| 150 | 154 | "INSERT OR IGNORE INTO localfiles" |
| 151 | - " SELECT pathelement(name,%d), NULL FROM filename" | |
| 155 | + " SELECT pathelement(name,%d), NULL, NULL FROM filename" | |
| 152 | 156 | " WHERE name GLOB '%q/*'", |
| 153 | 157 | nD, zD |
| 154 | 158 | ); |
| 155 | 159 | }else{ |
| 156 | 160 | db_multi_exec( |
| @@ -166,11 +170,11 @@ | ||
| 166 | 170 | " SELECT pathelement(name,0), NULL FROM filename" |
| 167 | 171 | ); |
| 168 | 172 | } |
| 169 | 173 | |
| 170 | 174 | if(zCI){ |
| 171 | - db_prepare( &q, "SELECT x as name, u as uuid FROM localfiles ORDER BY x"); | |
| 175 | + db_prepare( &q, "SELECT x as name, u as uuid, sz as size FROM localfiles ORDER BY x"); | |
| 172 | 176 | }else{/* UUIDs are all NULL. */ |
| 173 | 177 | db_prepare( &q, "SELECT x as name FROM localfiles ORDER BY x"); |
| 174 | 178 | } |
| 175 | 179 | |
| 176 | 180 | zKeyName = cson_new_string("name",4); |
| @@ -177,49 +181,66 @@ | ||
| 177 | 181 | cson_value_add_reference( cson_string_value(zKeyName) ); |
| 178 | 182 | zKeyUuid = cson_new_string("uuid",4); |
| 179 | 183 | cson_value_add_reference( cson_string_value(zKeyUuid) ); |
| 180 | 184 | zKeyIsDir = cson_new_string("isDir",5); |
| 181 | 185 | cson_value_add_reference( cson_string_value(zKeyIsDir) ); |
| 186 | + if( zCI ){ | |
| 187 | + zKeySize = cson_new_string("size",4); | |
| 188 | + cson_value_add_reference( cson_string_value(zKeySize) ); | |
| 189 | + } | |
| 182 | 190 | |
| 183 | 191 | zPayload = cson_new_object(); |
| 184 | - cson_object_set_s( zPayload, zKeyName, json_new_string((zD&&*zD) ? zD : "/") ); | |
| 192 | + cson_object_set_s( zPayload, zKeyName, | |
| 193 | + json_new_string((zD&&*zD) ? zD : "/") ); | |
| 185 | 194 | if(zUuid){ |
| 186 | - cson_object_set_s( zPayload, zKeyUuid, cson_string_value(cson_new_string(zUuid, strlen(zUuid))) ); | |
| 195 | + cson_object_set_s( zPayload, zKeyUuid, | |
| 196 | + cson_string_value(cson_new_string(zUuid, strlen(zUuid))) ); | |
| 187 | 197 | } |
| 188 | 198 | if( zCI ){ |
| 189 | 199 | cson_object_set( zPayload, "checkin", json_new_string(zCI) ); |
| 190 | 200 | } |
| 191 | 201 | |
| 192 | 202 | while( (SQLITE_ROW==db_step(&q)) ){ |
| 193 | 203 | cson_value * name = NULL; |
| 194 | 204 | char const * n = db_column_text(&q,0); |
| 195 | - char const * u = zCI ? db_column_text(&q,1) : NULL; | |
| 205 | + char const isDir = ('/'==*n); | |
| 196 | 206 | zEntry = cson_new_object(); |
| 197 | 207 | if(!zEntries){ |
| 198 | 208 | zEntries = cson_new_array(); |
| 199 | 209 | cson_object_set( zPayload, "entries", cson_array_value(zEntries) ); |
| 200 | 210 | } |
| 201 | - if('/'==*n){ | |
| 211 | + cson_array_append(zEntries, cson_object_value(zEntry) ); | |
| 212 | + if(isDir){ | |
| 202 | 213 | name = json_new_string( n+1 ); |
| 203 | 214 | cson_object_set_s(zEntry, zKeyIsDir, cson_value_true() ); |
| 204 | - | |
| 205 | 215 | } else{ |
| 206 | 216 | name = json_new_string( n ); |
| 207 | 217 | } |
| 208 | - if(u && *u){ | |
| 209 | - cson_object_set_s(zEntry, zKeyUuid, json_new_string( u ) ); | |
| 210 | - } | |
| 211 | 218 | cson_object_set_s(zEntry, zKeyName, name ); |
| 212 | - cson_array_append(zEntries, cson_object_value(zEntry) ); | |
| 219 | + if( zCI ){ | |
| 220 | + char const * u = db_column_text(&q,1); | |
| 221 | + sqlite_int64 const sz = db_column_int64(&q,2); | |
| 222 | + if(!isDir){ | |
| 223 | + /* don't add the uuid/size for dir entries - that data refers | |
| 224 | + to one of the files in that directory :/. */ | |
| 225 | + if(u && *u){ | |
| 226 | + cson_object_set_s(zEntry, zKeyUuid, json_new_string( u ) ); | |
| 227 | + } | |
| 228 | + cson_object_set_s(zEntry, zKeySize, | |
| 229 | + cson_value_new_integer( (cson_int_t)sz )); | |
| 230 | + } | |
| 231 | + } | |
| 213 | 232 | } |
| 214 | 233 | db_finalize(&q); |
| 215 | 234 | if(pM){ |
| 216 | 235 | manifest_destroy(pM); |
| 217 | 236 | } |
| 218 | - cson_value_free( cson_string_value( zKeyName ) ); | |
| 219 | - cson_value_free( cson_string_value( zKeyUuid ) ); | |
| 220 | - cson_value_free( cson_string_value( zKeyIsDir ) ); | |
| 237 | + cson_value_free( cson_string_value( zKeyName ) ); | |
| 238 | + cson_value_free( cson_string_value( zKeyUuid ) ); | |
| 239 | + cson_value_free( cson_string_value( zKeyIsDir ) ); | |
| 240 | + cson_value_free( cson_string_value( zKeySize ) ); | |
| 241 | + | |
| 221 | 242 | free( zUuid ); |
| 222 | 243 | free( zD ); |
| 223 | 244 | return cson_object_value(zPayload); |
| 224 | 245 | } |
| 225 | 246 | |
| 226 | 247 |
| --- src/json_dir.c | |
| +++ src/json_dir.c | |
| @@ -50,10 +50,11 @@ | |
| 50 | static cson_value * json_page_dir_list(){ |
| 51 | cson_object * zPayload = NULL; |
| 52 | cson_array * zEntries = NULL; |
| 53 | cson_object * zEntry = NULL; |
| 54 | cson_string * zKeyName = NULL; |
| 55 | cson_string * zKeyIsDir = NULL; |
| 56 | cson_string * zKeyUuid = NULL; |
| 57 | char * zD = NULL; |
| 58 | char const * zDX = NULL; |
| 59 | cson_value const * zDV = NULL; |
| @@ -105,11 +106,11 @@ | |
| 105 | ** Subdirectory names begin with "/". This causes them to sort |
| 106 | ** first and it also gives us an easy way to distinguish files |
| 107 | ** from directories in the loop that follows. |
| 108 | */ |
| 109 | db_multi_exec( |
| 110 | "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u);", |
| 111 | filename_collation() |
| 112 | ); |
| 113 | |
| 114 | if( zCI ){ |
| 115 | Stmt ins; |
| @@ -117,11 +118,13 @@ | |
| 117 | ManifestFile *pPrev = 0; |
| 118 | int nPrev = 0; |
| 119 | int c; |
| 120 | |
| 121 | db_prepare(&ins, |
| 122 | "INSERT OR IGNORE INTO localfiles VALUES(pathelement(:x,0), :u)" |
| 123 | ); |
| 124 | manifest_file_rewind(pM); |
| 125 | while( (pFile = manifest_file_next(pM,0))!=0 ){ |
| 126 | if( nD>0 |
| 127 | && ((pFile->zName[nD-1]!='/') || (0!=memcmp(pFile->zName, zD, nD-1))) |
| @@ -135,10 +138,11 @@ | |
| 135 | ){ |
| 136 | continue; |
| 137 | } |
| 138 | db_bind_text(&ins, ":x", &pFile->zName[nD]); |
| 139 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 140 | db_step(&ins); |
| 141 | db_reset(&ins); |
| 142 | pPrev = pFile; |
| 143 | for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} |
| 144 | if( c=='/' ) nPrev++; |
| @@ -146,11 +150,11 @@ | |
| 146 | db_finalize(&ins); |
| 147 | }else if( zD && *zD ){ |
| 148 | if( filenames_are_case_sensitive() ){ |
| 149 | db_multi_exec( |
| 150 | "INSERT OR IGNORE INTO localfiles" |
| 151 | " SELECT pathelement(name,%d), NULL FROM filename" |
| 152 | " WHERE name GLOB '%q/*'", |
| 153 | nD, zD |
| 154 | ); |
| 155 | }else{ |
| 156 | db_multi_exec( |
| @@ -166,11 +170,11 @@ | |
| 166 | " SELECT pathelement(name,0), NULL FROM filename" |
| 167 | ); |
| 168 | } |
| 169 | |
| 170 | if(zCI){ |
| 171 | db_prepare( &q, "SELECT x as name, u as uuid FROM localfiles ORDER BY x"); |
| 172 | }else{/* UUIDs are all NULL. */ |
| 173 | db_prepare( &q, "SELECT x as name FROM localfiles ORDER BY x"); |
| 174 | } |
| 175 | |
| 176 | zKeyName = cson_new_string("name",4); |
| @@ -177,49 +181,66 @@ | |
| 177 | cson_value_add_reference( cson_string_value(zKeyName) ); |
| 178 | zKeyUuid = cson_new_string("uuid",4); |
| 179 | cson_value_add_reference( cson_string_value(zKeyUuid) ); |
| 180 | zKeyIsDir = cson_new_string("isDir",5); |
| 181 | cson_value_add_reference( cson_string_value(zKeyIsDir) ); |
| 182 | |
| 183 | zPayload = cson_new_object(); |
| 184 | cson_object_set_s( zPayload, zKeyName, json_new_string((zD&&*zD) ? zD : "/") ); |
| 185 | if(zUuid){ |
| 186 | cson_object_set_s( zPayload, zKeyUuid, cson_string_value(cson_new_string(zUuid, strlen(zUuid))) ); |
| 187 | } |
| 188 | if( zCI ){ |
| 189 | cson_object_set( zPayload, "checkin", json_new_string(zCI) ); |
| 190 | } |
| 191 | |
| 192 | while( (SQLITE_ROW==db_step(&q)) ){ |
| 193 | cson_value * name = NULL; |
| 194 | char const * n = db_column_text(&q,0); |
| 195 | char const * u = zCI ? db_column_text(&q,1) : NULL; |
| 196 | zEntry = cson_new_object(); |
| 197 | if(!zEntries){ |
| 198 | zEntries = cson_new_array(); |
| 199 | cson_object_set( zPayload, "entries", cson_array_value(zEntries) ); |
| 200 | } |
| 201 | if('/'==*n){ |
| 202 | name = json_new_string( n+1 ); |
| 203 | cson_object_set_s(zEntry, zKeyIsDir, cson_value_true() ); |
| 204 | |
| 205 | } else{ |
| 206 | name = json_new_string( n ); |
| 207 | } |
| 208 | if(u && *u){ |
| 209 | cson_object_set_s(zEntry, zKeyUuid, json_new_string( u ) ); |
| 210 | } |
| 211 | cson_object_set_s(zEntry, zKeyName, name ); |
| 212 | cson_array_append(zEntries, cson_object_value(zEntry) ); |
| 213 | } |
| 214 | db_finalize(&q); |
| 215 | if(pM){ |
| 216 | manifest_destroy(pM); |
| 217 | } |
| 218 | cson_value_free( cson_string_value( zKeyName ) ); |
| 219 | cson_value_free( cson_string_value( zKeyUuid ) ); |
| 220 | cson_value_free( cson_string_value( zKeyIsDir ) ); |
| 221 | free( zUuid ); |
| 222 | free( zD ); |
| 223 | return cson_object_value(zPayload); |
| 224 | } |
| 225 | |
| 226 |
| --- src/json_dir.c | |
| +++ src/json_dir.c | |
| @@ -50,10 +50,11 @@ | |
| 50 | static cson_value * json_page_dir_list(){ |
| 51 | cson_object * zPayload = NULL; |
| 52 | cson_array * zEntries = NULL; |
| 53 | cson_object * zEntry = NULL; |
| 54 | cson_string * zKeyName = NULL; |
| 55 | cson_string * zKeySize = NULL; |
| 56 | cson_string * zKeyIsDir = NULL; |
| 57 | cson_string * zKeyUuid = NULL; |
| 58 | char * zD = NULL; |
| 59 | char const * zDX = NULL; |
| 60 | cson_value const * zDV = NULL; |
| @@ -105,11 +106,11 @@ | |
| 106 | ** Subdirectory names begin with "/". This causes them to sort |
| 107 | ** first and it also gives us an easy way to distinguish files |
| 108 | ** from directories in the loop that follows. |
| 109 | */ |
| 110 | db_multi_exec( |
| 111 | "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u, sz);", |
| 112 | filename_collation() |
| 113 | ); |
| 114 | |
| 115 | if( zCI ){ |
| 116 | Stmt ins; |
| @@ -117,11 +118,13 @@ | |
| 118 | ManifestFile *pPrev = 0; |
| 119 | int nPrev = 0; |
| 120 | int c; |
| 121 | |
| 122 | db_prepare(&ins, |
| 123 | "INSERT OR IGNORE INTO localfiles VALUES(pathelement(:x,0), :u, " |
| 124 | "(SELECT size from blob where uuid=:s)" |
| 125 | ")" |
| 126 | ); |
| 127 | manifest_file_rewind(pM); |
| 128 | while( (pFile = manifest_file_next(pM,0))!=0 ){ |
| 129 | if( nD>0 |
| 130 | && ((pFile->zName[nD-1]!='/') || (0!=memcmp(pFile->zName, zD, nD-1))) |
| @@ -135,10 +138,11 @@ | |
| 138 | ){ |
| 139 | continue; |
| 140 | } |
| 141 | db_bind_text(&ins, ":x", &pFile->zName[nD]); |
| 142 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 143 | db_bind_text(&ins, ":s", pFile->zUuid); |
| 144 | db_step(&ins); |
| 145 | db_reset(&ins); |
| 146 | pPrev = pFile; |
| 147 | for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} |
| 148 | if( c=='/' ) nPrev++; |
| @@ -146,11 +150,11 @@ | |
| 150 | db_finalize(&ins); |
| 151 | }else if( zD && *zD ){ |
| 152 | if( filenames_are_case_sensitive() ){ |
| 153 | db_multi_exec( |
| 154 | "INSERT OR IGNORE INTO localfiles" |
| 155 | " SELECT pathelement(name,%d), NULL, NULL FROM filename" |
| 156 | " WHERE name GLOB '%q/*'", |
| 157 | nD, zD |
| 158 | ); |
| 159 | }else{ |
| 160 | db_multi_exec( |
| @@ -166,11 +170,11 @@ | |
| 170 | " SELECT pathelement(name,0), NULL FROM filename" |
| 171 | ); |
| 172 | } |
| 173 | |
| 174 | if(zCI){ |
| 175 | db_prepare( &q, "SELECT x as name, u as uuid, sz as size FROM localfiles ORDER BY x"); |
| 176 | }else{/* UUIDs are all NULL. */ |
| 177 | db_prepare( &q, "SELECT x as name FROM localfiles ORDER BY x"); |
| 178 | } |
| 179 | |
| 180 | zKeyName = cson_new_string("name",4); |
| @@ -177,49 +181,66 @@ | |
| 181 | cson_value_add_reference( cson_string_value(zKeyName) ); |
| 182 | zKeyUuid = cson_new_string("uuid",4); |
| 183 | cson_value_add_reference( cson_string_value(zKeyUuid) ); |
| 184 | zKeyIsDir = cson_new_string("isDir",5); |
| 185 | cson_value_add_reference( cson_string_value(zKeyIsDir) ); |
| 186 | if( zCI ){ |
| 187 | zKeySize = cson_new_string("size",4); |
| 188 | cson_value_add_reference( cson_string_value(zKeySize) ); |
| 189 | } |
| 190 | |
| 191 | zPayload = cson_new_object(); |
| 192 | cson_object_set_s( zPayload, zKeyName, |
| 193 | json_new_string((zD&&*zD) ? zD : "/") ); |
| 194 | if(zUuid){ |
| 195 | cson_object_set_s( zPayload, zKeyUuid, |
| 196 | cson_string_value(cson_new_string(zUuid, strlen(zUuid))) ); |
| 197 | } |
| 198 | if( zCI ){ |
| 199 | cson_object_set( zPayload, "checkin", json_new_string(zCI) ); |
| 200 | } |
| 201 | |
| 202 | while( (SQLITE_ROW==db_step(&q)) ){ |
| 203 | cson_value * name = NULL; |
| 204 | char const * n = db_column_text(&q,0); |
| 205 | char const isDir = ('/'==*n); |
| 206 | zEntry = cson_new_object(); |
| 207 | if(!zEntries){ |
| 208 | zEntries = cson_new_array(); |
| 209 | cson_object_set( zPayload, "entries", cson_array_value(zEntries) ); |
| 210 | } |
| 211 | cson_array_append(zEntries, cson_object_value(zEntry) ); |
| 212 | if(isDir){ |
| 213 | name = json_new_string( n+1 ); |
| 214 | cson_object_set_s(zEntry, zKeyIsDir, cson_value_true() ); |
| 215 | } else{ |
| 216 | name = json_new_string( n ); |
| 217 | } |
| 218 | cson_object_set_s(zEntry, zKeyName, name ); |
| 219 | if( zCI ){ |
| 220 | char const * u = db_column_text(&q,1); |
| 221 | sqlite_int64 const sz = db_column_int64(&q,2); |
| 222 | if(!isDir){ |
| 223 | /* don't add the uuid/size for dir entries - that data refers |
| 224 | to one of the files in that directory :/. */ |
| 225 | if(u && *u){ |
| 226 | cson_object_set_s(zEntry, zKeyUuid, json_new_string( u ) ); |
| 227 | } |
| 228 | cson_object_set_s(zEntry, zKeySize, |
| 229 | cson_value_new_integer( (cson_int_t)sz )); |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | db_finalize(&q); |
| 234 | if(pM){ |
| 235 | manifest_destroy(pM); |
| 236 | } |
| 237 | cson_value_free( cson_string_value( zKeyName ) ); |
| 238 | cson_value_free( cson_string_value( zKeyUuid ) ); |
| 239 | cson_value_free( cson_string_value( zKeyIsDir ) ); |
| 240 | cson_value_free( cson_string_value( zKeySize ) ); |
| 241 | |
| 242 | free( zUuid ); |
| 243 | free( zD ); |
| 244 | return cson_object_value(zPayload); |
| 245 | } |
| 246 | |
| 247 |
+22
-28
| --- src/json_finfo.c | ||
| +++ src/json_finfo.c | ||
| @@ -45,35 +45,36 @@ | ||
| 45 | 45 | json_warn( FSL_JSON_W_UNKNOWN, "Achtung: the output of the finfo command is up for change."); |
| 46 | 46 | |
| 47 | 47 | /* For the "name" argument we have to jump through some hoops to make sure that we don't |
| 48 | 48 | get the fossil-internally-assigned "name" option. |
| 49 | 49 | */ |
| 50 | - zFilename = json_find_option_cstr("name",NULL,NULL); | |
| 51 | - if(!zFilename && !g.isHTTP){ | |
| 52 | - zFilename = json_command_arg(g.json.dispatchDepth+1); | |
| 53 | - } | |
| 54 | - if(!zFilename){ | |
| 50 | + zFilename = json_find_option_cstr2("name",NULL,NULL, g.json.dispatchDepth+1); | |
| 51 | + if(!zFilename || !*zFilename){ | |
| 55 | 52 | json_set_err(FSL_JSON_E_MISSING_ARGS, "Missing 'name' parameter."); |
| 56 | 53 | return NULL; |
| 57 | 54 | } |
| 55 | + | |
| 56 | + if(0==db_int(0,"SELECT 1 FROM filename WHERE name=%Q",zFilename)){ | |
| 57 | + json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, "File entry not found."); | |
| 58 | + return NULL; | |
| 59 | + } | |
| 60 | + | |
| 58 | 61 | zBefore = json_find_option_cstr("before",NULL,"b"); |
| 59 | 62 | zAfter = json_find_option_cstr("after",NULL,"a"); |
| 60 | 63 | limit = json_find_option_int("limit",NULL,"n", -1); |
| 61 | 64 | zCheckin = json_find_option_cstr("checkin",NULL,"ci"); |
| 62 | 65 | |
| 63 | 66 | blob_appendf(&sql, |
| 64 | - "SELECT b.uuid," | |
| 65 | - " ci.uuid," | |
| 66 | - " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */ | |
| 67 | - " cast(strftime('%%s',event.mtime) AS INTEGER)," | |
| 68 | - " coalesce(event.euser, event.user)," | |
| 69 | - " coalesce(event.ecomment, event.comment)," | |
| 70 | -#if 1 | |
| 71 | - " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */ | |
| 72 | -#endif | |
| 73 | - " event.bgcolor," | |
| 74 | - " 1" | |
| 67 | +/*0*/ "SELECT b.uuid," | |
| 68 | +/*1*/ " ci.uuid," | |
| 69 | +/*2*/ " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */ | |
| 70 | +/*3*/ " cast(strftime('%%s',event.mtime) AS INTEGER)," | |
| 71 | +/*4*/ " coalesce(event.euser, event.user)," | |
| 72 | +/*5*/ " coalesce(event.ecomment, event.comment)," | |
| 73 | +/*6*/ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */ | |
| 74 | +/*7*/ " event.bgcolor," | |
| 75 | +/*8*/ " b.size" | |
| 75 | 76 | " FROM mlink, blob b, event, blob ci, filename" |
| 76 | 77 | " WHERE filename.name=%Q %s" |
| 77 | 78 | " AND mlink.fnid=filename.fnid" |
| 78 | 79 | " AND b.rid=mlink.fid" |
| 79 | 80 | " AND event.objid=mlink.mid" |
| @@ -82,26 +83,27 @@ | ||
| 82 | 83 | ); |
| 83 | 84 | |
| 84 | 85 | if( zCheckin && *zCheckin ){ |
| 85 | 86 | char * zU = NULL; |
| 86 | 87 | int rc = name_to_uuid2( zCheckin, "ci", &zU ); |
| 87 | - printf("zCheckin=[%s], zU=[%s]", zCheckin, zU); | |
| 88 | + /*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/ | |
| 88 | 89 | if(rc<=0){ |
| 89 | 90 | json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 90 | 91 | "Checkin UUID %s.", (rc<0) ? "is ambiguous" : "not found"); |
| 91 | 92 | blob_reset(&sql); |
| 92 | 93 | return NULL; |
| 93 | 94 | } |
| 94 | 95 | blob_appendf(&sql, " AND ci.uuid='%q'", zU); |
| 95 | 96 | free(zU); |
| 96 | 97 | }else{ |
| 97 | - if( zAfter ){ | |
| 98 | + if( zAfter && *zAfter ){ | |
| 98 | 99 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zAfter); |
| 99 | - }else if( zBefore ){ | |
| 100 | + }else if( zBefore && *zBefore ){ | |
| 100 | 101 | blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zBefore); |
| 101 | 102 | } |
| 102 | 103 | } |
| 104 | + | |
| 103 | 105 | blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); |
| 104 | 106 | /*printf("SQL=\n%s\n",blob_str(&sql));*/ |
| 105 | 107 | db_prepare(&q, "%s", blob_str(&sql)/*extra %s to avoid double-expanding |
| 106 | 108 | SQL escapes*/); |
| 107 | 109 | blob_reset(&sql); |
| @@ -121,26 +123,18 @@ | ||
| 121 | 123 | /*cson_object_set(row, "parentArtifact", json_new_string( db_column_text(&q,6) ));*/ |
| 122 | 124 | cson_object_set(row, "mtime", json_new_int( db_column_int(&q,3) )); |
| 123 | 125 | cson_object_set(row, "user", json_new_string( db_column_text(&q,4) )); |
| 124 | 126 | cson_object_set(row, "comment", json_new_string( db_column_text(&q,5) )); |
| 125 | 127 | /*cson_object_set(row, "bgColor", json_new_string( db_column_text(&q,7) ));*/ |
| 128 | + cson_object_set(row, "size", cson_value_new_integer( (cson_int_t)db_column_int64(&q,8) )); | |
| 126 | 129 | if( (0 < limit) && (++currentRow >= limit) ){ |
| 127 | 130 | break; |
| 128 | 131 | } |
| 129 | 132 | } |
| 130 | 133 | db_finalize(&q); |
| 131 | 134 | |
| 132 | - if( !cson_array_length_get(checkins) ){ | |
| 133 | - json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, | |
| 134 | - zCheckin | |
| 135 | - ? "File not part of the given checkin." | |
| 136 | - : "File not found." ); | |
| 137 | - cson_free_object(pay); | |
| 138 | - pay = NULL; | |
| 139 | - } | |
| 140 | - | |
| 141 | 135 | return pay ? cson_object_value(pay) : NULL; |
| 142 | 136 | } |
| 143 | 137 | |
| 144 | 138 | |
| 145 | 139 | |
| 146 | 140 | #endif /* FOSSIL_ENABLE_JSON */ |
| 147 | 141 |
| --- src/json_finfo.c | |
| +++ src/json_finfo.c | |
| @@ -45,35 +45,36 @@ | |
| 45 | json_warn( FSL_JSON_W_UNKNOWN, "Achtung: the output of the finfo command is up for change."); |
| 46 | |
| 47 | /* For the "name" argument we have to jump through some hoops to make sure that we don't |
| 48 | get the fossil-internally-assigned "name" option. |
| 49 | */ |
| 50 | zFilename = json_find_option_cstr("name",NULL,NULL); |
| 51 | if(!zFilename && !g.isHTTP){ |
| 52 | zFilename = json_command_arg(g.json.dispatchDepth+1); |
| 53 | } |
| 54 | if(!zFilename){ |
| 55 | json_set_err(FSL_JSON_E_MISSING_ARGS, "Missing 'name' parameter."); |
| 56 | return NULL; |
| 57 | } |
| 58 | zBefore = json_find_option_cstr("before",NULL,"b"); |
| 59 | zAfter = json_find_option_cstr("after",NULL,"a"); |
| 60 | limit = json_find_option_int("limit",NULL,"n", -1); |
| 61 | zCheckin = json_find_option_cstr("checkin",NULL,"ci"); |
| 62 | |
| 63 | blob_appendf(&sql, |
| 64 | "SELECT b.uuid," |
| 65 | " ci.uuid," |
| 66 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */ |
| 67 | " cast(strftime('%%s',event.mtime) AS INTEGER)," |
| 68 | " coalesce(event.euser, event.user)," |
| 69 | " coalesce(event.ecomment, event.comment)," |
| 70 | #if 1 |
| 71 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */ |
| 72 | #endif |
| 73 | " event.bgcolor," |
| 74 | " 1" |
| 75 | " FROM mlink, blob b, event, blob ci, filename" |
| 76 | " WHERE filename.name=%Q %s" |
| 77 | " AND mlink.fnid=filename.fnid" |
| 78 | " AND b.rid=mlink.fid" |
| 79 | " AND event.objid=mlink.mid" |
| @@ -82,26 +83,27 @@ | |
| 82 | ); |
| 83 | |
| 84 | if( zCheckin && *zCheckin ){ |
| 85 | char * zU = NULL; |
| 86 | int rc = name_to_uuid2( zCheckin, "ci", &zU ); |
| 87 | printf("zCheckin=[%s], zU=[%s]", zCheckin, zU); |
| 88 | if(rc<=0){ |
| 89 | json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 90 | "Checkin UUID %s.", (rc<0) ? "is ambiguous" : "not found"); |
| 91 | blob_reset(&sql); |
| 92 | return NULL; |
| 93 | } |
| 94 | blob_appendf(&sql, " AND ci.uuid='%q'", zU); |
| 95 | free(zU); |
| 96 | }else{ |
| 97 | if( zAfter ){ |
| 98 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zAfter); |
| 99 | }else if( zBefore ){ |
| 100 | blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zBefore); |
| 101 | } |
| 102 | } |
| 103 | blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); |
| 104 | /*printf("SQL=\n%s\n",blob_str(&sql));*/ |
| 105 | db_prepare(&q, "%s", blob_str(&sql)/*extra %s to avoid double-expanding |
| 106 | SQL escapes*/); |
| 107 | blob_reset(&sql); |
| @@ -121,26 +123,18 @@ | |
| 121 | /*cson_object_set(row, "parentArtifact", json_new_string( db_column_text(&q,6) ));*/ |
| 122 | cson_object_set(row, "mtime", json_new_int( db_column_int(&q,3) )); |
| 123 | cson_object_set(row, "user", json_new_string( db_column_text(&q,4) )); |
| 124 | cson_object_set(row, "comment", json_new_string( db_column_text(&q,5) )); |
| 125 | /*cson_object_set(row, "bgColor", json_new_string( db_column_text(&q,7) ));*/ |
| 126 | if( (0 < limit) && (++currentRow >= limit) ){ |
| 127 | break; |
| 128 | } |
| 129 | } |
| 130 | db_finalize(&q); |
| 131 | |
| 132 | if( !cson_array_length_get(checkins) ){ |
| 133 | json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 134 | zCheckin |
| 135 | ? "File not part of the given checkin." |
| 136 | : "File not found." ); |
| 137 | cson_free_object(pay); |
| 138 | pay = NULL; |
| 139 | } |
| 140 | |
| 141 | return pay ? cson_object_value(pay) : NULL; |
| 142 | } |
| 143 | |
| 144 | |
| 145 | |
| 146 | #endif /* FOSSIL_ENABLE_JSON */ |
| 147 |
| --- src/json_finfo.c | |
| +++ src/json_finfo.c | |
| @@ -45,35 +45,36 @@ | |
| 45 | json_warn( FSL_JSON_W_UNKNOWN, "Achtung: the output of the finfo command is up for change."); |
| 46 | |
| 47 | /* For the "name" argument we have to jump through some hoops to make sure that we don't |
| 48 | get the fossil-internally-assigned "name" option. |
| 49 | */ |
| 50 | zFilename = json_find_option_cstr2("name",NULL,NULL, g.json.dispatchDepth+1); |
| 51 | if(!zFilename || !*zFilename){ |
| 52 | json_set_err(FSL_JSON_E_MISSING_ARGS, "Missing 'name' parameter."); |
| 53 | return NULL; |
| 54 | } |
| 55 | |
| 56 | if(0==db_int(0,"SELECT 1 FROM filename WHERE name=%Q",zFilename)){ |
| 57 | json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, "File entry not found."); |
| 58 | return NULL; |
| 59 | } |
| 60 | |
| 61 | zBefore = json_find_option_cstr("before",NULL,"b"); |
| 62 | zAfter = json_find_option_cstr("after",NULL,"a"); |
| 63 | limit = json_find_option_int("limit",NULL,"n", -1); |
| 64 | zCheckin = json_find_option_cstr("checkin",NULL,"ci"); |
| 65 | |
| 66 | blob_appendf(&sql, |
| 67 | /*0*/ "SELECT b.uuid," |
| 68 | /*1*/ " ci.uuid," |
| 69 | /*2*/ " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */ |
| 70 | /*3*/ " cast(strftime('%%s',event.mtime) AS INTEGER)," |
| 71 | /*4*/ " coalesce(event.euser, event.user)," |
| 72 | /*5*/ " coalesce(event.ecomment, event.comment)," |
| 73 | /*6*/ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */ |
| 74 | /*7*/ " event.bgcolor," |
| 75 | /*8*/ " b.size" |
| 76 | " FROM mlink, blob b, event, blob ci, filename" |
| 77 | " WHERE filename.name=%Q %s" |
| 78 | " AND mlink.fnid=filename.fnid" |
| 79 | " AND b.rid=mlink.fid" |
| 80 | " AND event.objid=mlink.mid" |
| @@ -82,26 +83,27 @@ | |
| 83 | ); |
| 84 | |
| 85 | if( zCheckin && *zCheckin ){ |
| 86 | char * zU = NULL; |
| 87 | int rc = name_to_uuid2( zCheckin, "ci", &zU ); |
| 88 | /*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/ |
| 89 | if(rc<=0){ |
| 90 | json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 91 | "Checkin UUID %s.", (rc<0) ? "is ambiguous" : "not found"); |
| 92 | blob_reset(&sql); |
| 93 | return NULL; |
| 94 | } |
| 95 | blob_appendf(&sql, " AND ci.uuid='%q'", zU); |
| 96 | free(zU); |
| 97 | }else{ |
| 98 | if( zAfter && *zAfter ){ |
| 99 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zAfter); |
| 100 | }else if( zBefore && *zBefore ){ |
| 101 | blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zBefore); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); |
| 106 | /*printf("SQL=\n%s\n",blob_str(&sql));*/ |
| 107 | db_prepare(&q, "%s", blob_str(&sql)/*extra %s to avoid double-expanding |
| 108 | SQL escapes*/); |
| 109 | blob_reset(&sql); |
| @@ -121,26 +123,18 @@ | |
| 123 | /*cson_object_set(row, "parentArtifact", json_new_string( db_column_text(&q,6) ));*/ |
| 124 | cson_object_set(row, "mtime", json_new_int( db_column_int(&q,3) )); |
| 125 | cson_object_set(row, "user", json_new_string( db_column_text(&q,4) )); |
| 126 | cson_object_set(row, "comment", json_new_string( db_column_text(&q,5) )); |
| 127 | /*cson_object_set(row, "bgColor", json_new_string( db_column_text(&q,7) ));*/ |
| 128 | cson_object_set(row, "size", cson_value_new_integer( (cson_int_t)db_column_int64(&q,8) )); |
| 129 | if( (0 < limit) && (++currentRow >= limit) ){ |
| 130 | break; |
| 131 | } |
| 132 | } |
| 133 | db_finalize(&q); |
| 134 | |
| 135 | return pay ? cson_object_value(pay) : NULL; |
| 136 | } |
| 137 | |
| 138 | |
| 139 | |
| 140 | #endif /* FOSSIL_ENABLE_JSON */ |
| 141 |