diff --git a/ext/wasm/api/sqlite3-api-cleanup.js b/ext/wasm/api/sqlite3-api-cleanup.js index a2f921a5d7..ce24ad0137 100644 --- a/ext/wasm/api/sqlite3-api-cleanup.js +++ b/ext/wasm/api/sqlite3-api-cleanup.js @@ -16,29 +16,45 @@ various subsystems. */ 'use strict'; -self.sqlite3.postInit.forEach( - self.importScripts/*global is a Worker*/ - ? function(f){ - /** We try/catch/report for the sake of failures which happen in - a Worker, as those exceptions can otherwise get completely - swallowed, leading to confusing downstream errors which have - nothing to do with this failure. */ - try{ f(self, self.sqlite3) } - catch(e){ - console.error("Error in postInit() function:",e); - throw e; - } - } - : (f)=>f(self, self.sqlite3) -); -delete self.sqlite3.postInit; -if(self.location && +self.location.port > 1024){ - console.warn("Installing sqlite3 bits as global S for dev-testing purposes."); - self.S = self.sqlite3; -} -/* Clean up temporary global-scope references to our APIs... */ -self.sqlite3.config.Module.sqlite3 = self.sqlite3 -/* ^^^^ Currently needed by test code and Worker API setup */; -delete self.sqlite3.capi.util /* arguable, but these are (currently) internal-use APIs */; -delete self.sqlite3 /* clean up our global-scope reference */; -//console.warn("Module.sqlite3 =",Module.sqlite3); +(function(){ + /** + Replace sqlite3ApiBootstrap() with a variant which plugs in the + Emscripten-based config for all config options which the client + does not provide. + */ + const SAB = self.sqlite3ApiBootstrap; + self.sqlite3ApiBootstrap = function(apiConfig){ + apiConfig = apiConfig||{}; + const configDefaults = { + Module: Module /* ==> Emscripten-style Module object. Currently + needs to be exposed here for test code. NOT part + of the public API. */, + exports: Module['asm'], + memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */ + }; + const config = {}; + Object.keys(configDefaults).forEach(function(k){ + config[k] = Object.prototype.hasOwnProperty.call(apiConfig, k) + ? apiConfig[k] : configDefaults[k]; + }); + return SAB(config); + }; + + /** + For current (2022-08-22) purposes, automatically call sqlite3ApiBootstrap(). + That decision will be revisited at some point, as we really want client code + to be able to call this to configure certain parts. + */ + const sqlite3 = self.sqlite3ApiBootstrap(); + + if(self.location && +self.location.port > 1024){ + console.warn("Installing sqlite3 bits as global S for dev-testing purposes."); + self.S = sqlite3; + } + + /* Clean up temporary references to our APIs... */ + delete self.sqlite3ApiBootstrap; + Module.sqlite3 = sqlite3 /* Currently needed by test code */; + delete sqlite3.capi.util /* arguable, but these are (currently) internal-use APIs */; + //console.warn("Module.sqlite3 =",Module.sqlite3); +})(); diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js index efcd6fea9b..84bbdb10ac 100644 --- a/ext/wasm/api/sqlite3-api-glue.js +++ b/ext/wasm/api/sqlite3-api-glue.js @@ -16,23 +16,9 @@ initializes the main API pieces so that the downstream components (e.g. sqlite3-api-oo1.js) have all that they need. */ -(function(self){ +self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ 'use strict'; const toss = (...args)=>{throw new Error(args.join(' '))}; - - self.sqlite3 = self.sqlite3ApiBootstrap({ - Module: Module /* ==> Emscripten-style Module object. Currently - needs to be exposed here for test code. NOT part - of the public API. */, - exports: Module['asm'], - memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */, - bigIntEnabled: !!self.BigInt64Array, - allocExportName: 'malloc', - deallocExportName: 'free' - }); - delete self.sqlite3ApiBootstrap; - - const sqlite3 = self.sqlite3; const capi = sqlite3.capi, wasm = capi.wasm, util = capi.util; self.WhWasmUtilInstaller(capi.wasm); delete self.WhWasmUtilInstaller; @@ -57,7 +43,7 @@ return oldP(v); }; wasm.xWrap.argAdapter('.pointer', adapter); - } + } /* ".pointer" xWrap() argument adapter */ // WhWasmUtil.xWrap() bindings... { @@ -78,7 +64,7 @@ capi[e[0]] = wasm.xWrap.apply(null, e); } - /* For functions which cannot work properly unless + /* For C API functions which cannot work properly unless wasm.bigIntEnabled is true, install a bogus impl which throws if called when bigIntEnabled is false. */ const fI64Disabled = function(fname){ @@ -198,5 +184,4 @@ capi[s.name] = sqlite3.StructBinder(s); } } - -})(self); +}); diff --git a/ext/wasm/api/sqlite3-api-oo1.js b/ext/wasm/api/sqlite3-api-oo1.js index 0e04b63ebf..be9d8af5a8 100644 --- a/ext/wasm/api/sqlite3-api-oo1.js +++ b/ext/wasm/api/sqlite3-api-oo1.js @@ -14,10 +14,9 @@ WASM build. It requires that sqlite3-api-glue.js has already run and it installs its deliverable as self.sqlite3.oo1. */ -(function(self){ +self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const toss = (...args)=>{throw new Error(args.join(' '))}; - const sqlite3 = self.sqlite3 || toss("Missing main sqlite3 object."); const capi = sqlite3.capi, util = capi.util; /* What follows is colloquially known as "OO API #1". It is a binding of the sqlite3 API which is designed to be run within @@ -1547,5 +1546,6 @@ }, DB, Stmt - }/*SQLite3 object*/; -})(self); + }/*oo1 object*/; +}); + diff --git a/ext/wasm/api/sqlite3-api-opfs.js b/ext/wasm/api/sqlite3-api-opfs.js index 4acab7770a..693432b35a 100644 --- a/ext/wasm/api/sqlite3-api-opfs.js +++ b/ext/wasm/api/sqlite3-api-opfs.js @@ -31,12 +31,13 @@ // FileSystemDirectoryHandle // FileSystemFileHandle // FileSystemFileHandle.prototype.createSyncAccessHandle -self.sqlite3.postInit.push(function(self, sqlite3){ +self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const warn = console.warn.bind(console), error = console.error.bind(console); - if(!self.importScripts || !self.FileSystemFileHandle - || !self.FileSystemFileHandle.prototype.createSyncAccessHandle){ - warn("OPFS not found or its sync API is not available in this environment."); + if(!self.importScripts || !self.FileSystemFileHandle){ + //|| !self.FileSystemFileHandle.prototype.createSyncAccessHandle){ + // ^^^ sync API is not required with WASMFS/OPFS backend. + warn("OPFS is not available in this environment."); return; }else if(!sqlite3.capi.wasm.bigIntEnabled){ error("OPFS requires BigInt support but sqlite3.capi.wasm.bigIntEnabled is false."); diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index cf9fd896a6..87cc40b410 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -78,25 +78,88 @@ */ /** - This global symbol is is only a temporary measure: the JS-side - post-processing will remove that object from the global scope when - setup is complete. We require it there temporarily in order to glue - disparate parts together during the loading of the API (which spans - several components). + sqlite3ApiBootstrap() is the only global symbol exposed by this + API. It is intended to be called one time at the end of the API + amalgamation process, passed configuration details for the current + environment, and then optionally be removed from the global object + using `delete self.sqlite3ApiBootstrap`. - This function requires a configuration object intended to abstract + This function expects a configuration object, intended to abstract away details specific to any given WASM environment, primarily so - that it can be used without any _direct_ dependency on Emscripten. - (That said, OO API #1 requires, as of this writing, Emscripten's - virtual filesystem API. Baby steps.) + that it can be used without any _direct_ dependency on + Emscripten. The config object is only honored the first time this + is called. Subsequent calls ignore the argument and return the same + (configured) object which gets initialized by the first call. + + The config object properties include: + + - `Module`: Emscripten-style module object. Currently only required + by certain test code and is _not_ part of the public interface. + (TODO: rename this to EmscriptenModule to be more explicit.) + + - `exports`: the "exports" object for the current WASM + environment. In an Emscripten build, this should be set to + `Module['asm']`. + + - `memory`: optional WebAssembly.Memory object, defaulting to + `exports.memory`. In Emscripten environments this should be set + to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be + left undefined/falsy to default to `exports.memory` when using + WASM-exported memory. + + - `bigIntEnabled`: true if BigInt support is enabled. Defaults to + true if self.BigInt64Array is available, else false. Some APIs + will throw exceptions if called without BigInt support, as BigInt + is required for marshalling C-side int64 into and out of JS. + + - `allocExportName`: the name of the function, in `exports`, of the + `malloc(3)`-compatible routine for the WASM environment. Defaults + to `"malloc"`. + + - `deallocExportName`: the name of the function, in `exports`, of + the `free(3)`-compatible routine for the WASM + environment. Defaults to `"free"`. + + - `persistentDirName`: if the environment supports persistent storage, this + directory names the "mount point" for that directory. It must be prefixed + by `/` and may currently contain only a single directory-name part. Using + the root directory name is not supported by any current persistent backend. */ -self.sqlite3ApiBootstrap = function(config){ +self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(apiConfig){ 'use strict'; + + if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */ + console.warn("sqlite3ApiBootstrap() called multiple times.", + "Config and external initializers are ignored on calls after the first."); + return sqlite3ApiBootstrap.sqlite3; + } + + apiConfig = apiConfig||{}; + const config = Object.create(null); + { + const configDefaults = { + Module: undefined/*needed for some test code, not part of the public API*/, + exports: undefined, + memory: undefined, + bigIntEnabled: !!self.BigInt64Array, + allocExportName: 'malloc', + deallocExportName: 'free', + persistentDirName: '/persistent' + }; + Object.keys(configDefaults).forEach(function(k){ + config[k] = Object.prototype.hasOwnProperty.call(apiConfig, k) + ? apiConfig[k] : configDefaults[k]; + }); + } /** Throws a new Error, the message of which is the concatenation all args with a space between each. */ const toss = (...args)=>{throw new Error(args.join(' '))}; + if(config.persistentDirName && !/^\/[^/]+$/.test(config.persistentDirName)){ + toss("config.persistentDirName must be falsy or in the form '/dir-name'."); + } + /** Returns true if n is a 32-bit (signed) integer, else false. This is used for determining when we need to switch to @@ -143,7 +206,18 @@ self.sqlite3ApiBootstrap = function(config){ }; const utf8Decoder = new TextDecoder('utf-8'); - const typedArrayToString = (str)=>utf8Decoder.decode(str); + + /** Internal helper to use in operations which need to distinguish + between SharedArrayBuffer heap memory and non-shared heap. */ + const __SAB = ('undefined'===typeof SharedArrayBuffer) + ? function(){} : SharedArrayBuffer; + const typedArrayToString = function(arrayBuffer, begin, end){ + return utf8Decoder.decode( + (arrayBuffer.buffer instanceof __SAB) + ? arrayBuffer.slice(begin, end) + : arrayBuffer.subarray(begin, end) + ); + }; /** An Error subclass specifically for reporting Wasm-level malloc() @@ -591,9 +665,6 @@ self.sqlite3ApiBootstrap = function(config){ TODOs and caveats: - - The directory name (mount point) for persistent storage is - currently hard-coded. It needs to be configurable. - - If persistent storage is available at the root of the virtual filesystem, this interface cannot currently distinguish that from the lack of persistence. That case cannot currently (with @@ -604,12 +675,17 @@ self.sqlite3ApiBootstrap = function(config){ capi.sqlite3_web_persistent_dir = function(){ if(undefined !== __persistentDir) return __persistentDir; // If we have no OPFS, there is no persistent dir - if(!self.FileSystemHandle || !self.FileSystemDirectoryHandle + const pdir = config.persistentDirName; + if(!pdir + || !self.FileSystemHandle + || !self.FileSystemDirectoryHandle || !self.FileSystemFileHandle){ return __persistentDir = ""; } try{ - if(0===this.wasm.xCall('sqlite3_wasm_init_opfs')){ + if(pdir && 0===this.wasm.xCallWrapped( + 'sqlite3_wasm_init_opfs', 'i32', ['string'], pdir + )){ /** OPFS does not support locking and will trigger errors if we try to lock. We don't _really_ want to _unconditionally_ install a non-locking sqlite3 VFS as the @@ -617,13 +693,12 @@ self.sqlite3ApiBootstrap = function(config){ time being. That said: locking is a no-op on all of the current WASM storage, so this isn't (currently) as bad as it may initially seem. */ - const pVfs = this.sqlite3_vfs_find("unix-none"); + const pVfs = sqlite3.capi.sqlite3_vfs_find("unix-none"); if(pVfs){ - this.sqlite3_vfs_register(pVfs,1); - //warn("Installed 'unix-none' as the default sqlite3 VFS."); + capi.sqlite3_vfs_register(pVfs,1); + console.warn("Installed 'unix-none' as the default sqlite3 VFS."); } - return __persistentDir = - "/persistent" /* name is hard-coded in sqlite3_wasm_init_opfs()!*/; + return __persistentDir = pdir; }else{ return __persistentDir = ""; } @@ -644,19 +719,29 @@ self.sqlite3ApiBootstrap = function(config){ }.bind(capi); /* The remainder of the API will be set up in later steps. */ - return { - /** - An Error subclass which is thrown by this.wasm.alloc() on OOM. - */ + const sqlite3 = { WasmAllocError: WasmAllocError, capi, - postInit: [ - /* some pieces of the API may install functions into this array, - and each such function will be called, passed (self,sqlite3), - at the very end of the API load/init process, where self is - the current global object and sqlite3 is the object returned - from sqlite3ApiBootstrap(). This array will be removed at the - end of the API setup process. */], config }; + sqlite3ApiBootstrap.initializers.forEach((f)=>f(sqlite3)); + delete sqlite3ApiBootstrap.initializers; + sqlite3ApiBootstrap.sqlite3 = sqlite3; + return sqlite3; }/*sqlite3ApiBootstrap()*/; +/** + self.sqlite3ApiBootstrap.initializers is an internal detail used by + the various pieces of the sqlite3 API's amalgamation process. It + must not be modified by client code except when plugging such code + into the amalgamation process. + + Each component of the amalgamation is expected to append a function + to this array. When sqlite3ApiBootstrap() is called for the first + time, each such function will be called (in their appended order) + and passed the sqlite3 namespace object, into which they can install + their features (noting that most will also require that certain + features alread have been installed). At the end of that process, + this array is deleted. +*/ +self.sqlite3ApiBootstrap.initializers = []; +self.sqlite3ApiBootstrap.sqlite3 = undefined /* installed at first call */; diff --git a/ext/wasm/api/sqlite3-api-worker1.js b/ext/wasm/api/sqlite3-api-worker1.js index 565946bbc6..a7b759851f 100644 --- a/ext/wasm/api/sqlite3-api-worker1.js +++ b/ext/wasm/api/sqlite3-api-worker1.js @@ -43,7 +43,8 @@ In some contexts, however, listening for the above message is a better fit. */ -self.sqlite3.initWorker1API = function(){ +self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ +sqlite3.initWorker1API = function(){ 'use strict'; /** UNDER CONSTRUCTION @@ -418,4 +419,6 @@ self.sqlite3.initWorker1API = function(){ wState.post(evType, response, wMsgHandler.xfer); }; setTimeout(()=>self.postMessage({type:'sqlite3-api',data:'worker1-ready'}), 0); -}.bind({self, sqlite3: self.sqlite3}); +}.bind({self, sqlite3}); +}); + diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index 487baecf10..070282b8ee 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -435,7 +435,8 @@ int sqlite3_wasm_vfs_unlink(const char * zName){ #include /* ** This function is NOT part of the sqlite3 public API. It is strictly -** for use by the sqlite project's own JS/WASM bindings. +** for use by the sqlite project's own JS/WASM bindings, specifically +** only when building with Emscripten's WASMFS support. ** ** This function should only be called if the JS side detects the ** existence of the Origin-Private FileSystem (OPFS) APIs in the @@ -443,14 +444,19 @@ int sqlite3_wasm_vfs_unlink(const char * zName){ ** WASMFS backend impl for OPFS. On success, subsequent calls are ** no-ops. ** +** This function may be passed a "mount point" name, which must have a +** leading "/" and is currently restricted to a single path component, +** e.g. "/foo" is legal but "/foo/" and "/foo/bar" are not. If it is +** NULL or empty, it defaults to "/persistent". +** ** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend -** object fails, SQLITE_IOERR if mkdir() of the "/persistent" dir in +** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in ** the virtual FS fails. In builds compiled without SQLITE_WASM_OPFS ** defined, SQLITE_NOTFOUND is returned without side effects. */ -int sqlite3_wasm_init_opfs(void){ +int sqlite3_wasm_init_opfs(const char *zMountPoint){ static backend_t pOpfs = 0; - static const char * zDir = "/persistent"; + if( !zMountPoint || !*zMountPoint ) zMountPoint = "/persistent"; if( !pOpfs ){ pOpfs = wasmfs_create_opfs_backend(); if( pOpfs ){ @@ -459,12 +465,15 @@ int sqlite3_wasm_init_opfs(void){ } /** It's not enough to instantiate the backend. We have to create a mountpoint in the VFS and attach the backend to it. */ - if( pOpfs && 0!=access(zDir, F_OK) ){ + if( pOpfs && 0!=access(zMountPoint, F_OK) ){ /* mkdir() simply hangs when called from fiddle app. Cause is not yet determined but the hypothesis is an init-order issue. */ - const int rc = wasmfs_create_directory(zDir, 0777, pOpfs); - emscripten_console_log(rc ? "OPFS mkdir failed." : "OPFS mkdir ok."); + /* Note that this check and is not robust but it will + hypothetically suffice for the transient wasm-based virtual + filesystem we're currently running in. */ + const int rc = wasmfs_create_directory(zMountPoint, 0777, pOpfs); + emscripten_console_logf("OPFS mkdir rc=%d", rc); if(rc) return SQLITE_IOERR; } return pOpfs ? 0 : SQLITE_NOMEM; diff --git a/manifest b/manifest index 9faf2e216e..8ae71848be 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C wasm:\saccommodated\sa\sJS\sAPI\srename. -D 2022-08-22T08:55:10.642 +C Refactor\sJS\sAPI\samalgamation\ssuch\sthat\sthe\sbootstrapping/configuration\sis\sdeferred\suntil\sthe\swhole\samalgamation\sis\savailable,\sto\sfacilitate\sproviding\sclients\swith\sa\sway\sto\sinitialize\sthe\sAPI\swith\stheir\sown\sconfig\s(noting\sthat\swe're\sstill\sone\ssmall\slevel\sof\srefactoring\saway\sfrom\sbeing\sable\sto\sactually\sdo\sthat). +D 2022-08-22T13:34:13.519 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -481,14 +481,14 @@ F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de F ext/wasm/api/README.md d876597edd2b9542b6ea031adaaff1c042076fde7b670b1dc6d8a87b28a6631b F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba81456260a713ed04900c F ext/wasm/api/post-js-header.js 0e853b78db83cb1c06b01663549e0e8b4f377f12f5a2d9a4a06cb776c003880b -F ext/wasm/api/sqlite3-api-cleanup.js 149fd63a0400cd1d69548887ffde2ed89c13283384a63c2e9fcfc695e38a9e11 -F ext/wasm/api/sqlite3-api-glue.js 4a09dd1153874f7a716cf953329bc1e78bf24e0870a9aad15214ffd51ac913bc -F ext/wasm/api/sqlite3-api-oo1.js 6c14e97987fafdd5f63ffa8a086e5316d49c115743add4dabfacb302a7c76b45 -F ext/wasm/api/sqlite3-api-opfs.js c93cdd14f81a26b3a64990515ee05c7e29827fbc8fba4e4c2fef3a37a984db89 -F ext/wasm/api/sqlite3-api-prologue.js 96997e411b41ff3d4024c2ad625c5cdb7b6a619ba8beece4662ad190191b1119 -F ext/wasm/api/sqlite3-api-worker1.js 74130ec4979baeaf3e909c7619b99e9f466e2d816cd07370987ff639d168ef45 +F ext/wasm/api/sqlite3-api-cleanup.js eee5ac931fa0aee2cace52a0dff0cf22ae56a1993a88d911bd0dd384fb380c9a +F ext/wasm/api/sqlite3-api-glue.js 67ca83974410961953eeaa1dfed3518530d68381729ed1d27f95122f5baeabd3 +F ext/wasm/api/sqlite3-api-oo1.js f6dcaac3270182471f97efcfda25bd4a4ac1777b8ec52ebd1c6846721160e54c +F ext/wasm/api/sqlite3-api-opfs.js 011799db398157cbd254264b6ebae00d7234b93d0e9e810345f213a5774993c0 +F ext/wasm/api/sqlite3-api-prologue.js 5d1b13b23af48ce952e30a0f2d6dff4bc4b33f2dc36fdcaf69c164fd9a72b60f +F ext/wasm/api/sqlite3-api-worker1.js ceb1fc88d8a3742c069632e88fd05c14d5a79eb86bdb9e12969ec37f64fbf42b F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 -F ext/wasm/api/sqlite3-wasm.c 0e78035045e3328fb050ec9580c6bfb714c756a1d3b917259e58baf9b0332c98 +F ext/wasm/api/sqlite3-wasm.c 0d81282eaeff2a6e9fc5c28a388c5c5b45cf25a9393992fa511ac009b27df982 F ext/wasm/common/SqliteTestUtil.js e41a1406f18da9224523fad0c48885caf995b56956a5b9852909c0989e687e90 F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/common/testing.css 572cf1ffae0b6eb7ca63684d3392bf350217a07b90e7a896e4fa850700c989b0 @@ -2006,8 +2006,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7a3c444fb515413254b426908e4d3528ccc664a629628c23b7b85bd21c060d0e -R 763c38437f86fddfab452c17546273d5 +P 00991335c4dae56232e999398e5e82d8161903ba7d084b16a73a150e83f1f782 +R d8e7cfc53479bc2a5e5d34dd2cc26aa3 U stephan -Z 9e445c1e5e3ac9504605b874a5870c61 +Z dd954bd42edcc1a06b3b31bdffb215a4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f81e130264..174e4d0afc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -00991335c4dae56232e999398e5e82d8161903ba7d084b16a73a150e83f1f782 \ No newline at end of file +9dbe9a6aecec43b51057375ef1d2d632db0d17eac8b7552c20cc91fc2f1a55d1 \ No newline at end of file