mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
More internal refactoring and docs for opfs-sahpool.
FossilOrigin-Name: 64ccf6177a019eab46fb3345ad1e8ba80eaf2c9da55767031f9f04ccd16afb4d
This commit is contained in:
@ -48,8 +48,9 @@
|
|||||||
incompatible with that VFS.
|
incompatible with that VFS.
|
||||||
|
|
||||||
- This VFS requires the "semi-fully-sync" FileSystemSyncAccessHandle
|
- This VFS requires the "semi-fully-sync" FileSystemSyncAccessHandle
|
||||||
(hereafter "SAH") APIs released with Chrome v108. If that API
|
(hereafter "SAH") APIs released with Chrome v108 (and all other
|
||||||
is not detected, the VFS is not registered.
|
major browsers released since March 2023). If that API is not
|
||||||
|
detected, the VFS is not registered.
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||||
@ -137,11 +138,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
xClose: function(pFile){
|
xClose: function(pFile){
|
||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.storeErr();
|
pool.storeErr();
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
if(file) {
|
if(file) {
|
||||||
try{
|
try{
|
||||||
pool.log(`xClose ${file.path}`);
|
pool.log(`xClose ${file.path}`);
|
||||||
pool.setFileForPtr(pFile, false);
|
pool.mapSFileToOFile(pFile, false);
|
||||||
file.sah.flush();
|
file.sah.flush();
|
||||||
if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){
|
if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){
|
||||||
pool.deletePath(file.path);
|
pool.deletePath(file.path);
|
||||||
@ -162,7 +163,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
xFileSize: function(pFile,pSz64){
|
xFileSize: function(pFile,pSz64){
|
||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.log(`xFileSize`);
|
pool.log(`xFileSize`);
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
const size = file.sah.getSize() - HEADER_OFFSET_DATA;
|
const size = file.sah.getSize() - HEADER_OFFSET_DATA;
|
||||||
//log(`xFileSize ${file.path} ${size}`);
|
//log(`xFileSize ${file.path} ${size}`);
|
||||||
wasm.poke64(pSz64, BigInt(size));
|
wasm.poke64(pSz64, BigInt(size));
|
||||||
@ -172,14 +173,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.log(`xLock ${lockType}`);
|
pool.log(`xLock ${lockType}`);
|
||||||
pool.storeErr();
|
pool.storeErr();
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
file.lockType = lockType;
|
file.lockType = lockType;
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
xRead: function(pFile,pDest,n,offset64){
|
xRead: function(pFile,pDest,n,offset64){
|
||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.storeErr();
|
pool.storeErr();
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
pool.log(`xRead ${file.path} ${n} @ ${offset64}`);
|
pool.log(`xRead ${file.path} ${n} @ ${offset64}`);
|
||||||
try {
|
try {
|
||||||
const nRead = file.sah.read(
|
const nRead = file.sah.read(
|
||||||
@ -203,7 +204,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.log(`xSync ${flags}`);
|
pool.log(`xSync ${flags}`);
|
||||||
pool.storeErr();
|
pool.storeErr();
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
//log(`xSync ${file.path} ${flags}`);
|
//log(`xSync ${file.path} ${flags}`);
|
||||||
try{
|
try{
|
||||||
file.sah.flush();
|
file.sah.flush();
|
||||||
@ -217,7 +218,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.log(`xTruncate ${sz64}`);
|
pool.log(`xTruncate ${sz64}`);
|
||||||
pool.storeErr();
|
pool.storeErr();
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
//log(`xTruncate ${file.path} ${iSize}`);
|
//log(`xTruncate ${file.path} ${iSize}`);
|
||||||
try{
|
try{
|
||||||
file.sah.truncate(HEADER_OFFSET_DATA + Number(sz64));
|
file.sah.truncate(HEADER_OFFSET_DATA + Number(sz64));
|
||||||
@ -230,14 +231,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
xUnlock: function(pFile,lockType){
|
xUnlock: function(pFile,lockType){
|
||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.log('xUnlock');
|
pool.log('xUnlock');
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
file.lockType = lockType;
|
file.lockType = lockType;
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
xWrite: function(pFile,pSrc,n,offset64){
|
xWrite: function(pFile,pSrc,n,offset64){
|
||||||
const pool = getPoolForPFile(pFile);
|
const pool = getPoolForPFile(pFile);
|
||||||
pool.storeErr();
|
pool.storeErr();
|
||||||
const file = pool.getFileForPtr(pFile);
|
const file = pool.getOFileForSFile(pFile);
|
||||||
pool.log(`xWrite ${file.path} ${n} ${offset64}`);
|
pool.log(`xWrite ${file.path} ${n} ${offset64}`);
|
||||||
try{
|
try{
|
||||||
const nBytes = file.sah.write(
|
const nBytes = file.sah.write(
|
||||||
@ -349,7 +350,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
// Subsequent I/O methods are only passed the sqlite3_file
|
// Subsequent I/O methods are only passed the sqlite3_file
|
||||||
// pointer, so map the relevant info we need to that pointer.
|
// pointer, so map the relevant info we need to that pointer.
|
||||||
const file = {path, flags, sah};
|
const file = {path, flags, sah};
|
||||||
pool.setFileForPtr(pFile, file);
|
pool.mapSFileToOFile(pFile, file);
|
||||||
file.lockType = capi.SQLITE_LOCK_NONE;
|
file.lockType = capi.SQLITE_LOCK_NONE;
|
||||||
const sq3File = new capi.sqlite3_file(pFile);
|
const sq3File = new capi.sqlite3_file(pFile);
|
||||||
sq3File.$pMethods = opfsIoMethods.pointer;
|
sq3File.$pMethods = opfsIoMethods.pointer;
|
||||||
@ -436,6 +437,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
|
|
||||||
/** Buffer used by [sg]etAssociatedPath(). */
|
/** Buffer used by [sg]etAssociatedPath(). */
|
||||||
#apBody = new Uint8Array(HEADER_CORPUS_SIZE);
|
#apBody = new Uint8Array(HEADER_CORPUS_SIZE);
|
||||||
|
// DataView for this.#apBody
|
||||||
#dvBody;
|
#dvBody;
|
||||||
|
|
||||||
// associated sqlite3_vfs instance
|
// associated sqlite3_vfs instance
|
||||||
@ -497,6 +499,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return this.getCapacity();
|
return this.getCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reduce capacity by n, but can only reduce up to the limit
|
||||||
|
of currently-available SAHs. Returns a Promise which resolves
|
||||||
|
to the number of slots really removed.
|
||||||
|
*/
|
||||||
async reduceCapacity(n){
|
async reduceCapacity(n){
|
||||||
let nRm = 0;
|
let nRm = 0;
|
||||||
for(const ah of Array.from(this.#availableSAH)){
|
for(const ah of Array.from(this.#availableSAH)){
|
||||||
@ -514,7 +521,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Releases all currently-opened SAHs.
|
Releases all currently-opened SAHs. The only legal
|
||||||
|
operation after this is acquireAccessHandles().
|
||||||
*/
|
*/
|
||||||
releaseAccessHandles(){
|
releaseAccessHandles(){
|
||||||
for(const ah of this.#mapSAHToName.keys()) ah.close();
|
for(const ah of this.#mapSAHToName.keys()) ah.close();
|
||||||
@ -637,8 +645,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Computes a digest for the given byte array and
|
Computes a digest for the given byte array and returns it as a
|
||||||
returns it as a two-element Uint32Array.
|
two-element Uint32Array. This digest gets stored in the
|
||||||
|
metadata for each file as a validation check. Changing this
|
||||||
|
algorithm invalidates all existing databases for this VFS, so
|
||||||
|
don't do that.
|
||||||
*/
|
*/
|
||||||
computeDigest(byteArray){
|
computeDigest(byteArray){
|
||||||
let h1 = 0xdeadbeef;
|
let h1 = 0xdeadbeef;
|
||||||
@ -730,14 +741,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFileForPtr(ptr){
|
/**
|
||||||
|
Given an (sqlite3_file*), returns the mapped
|
||||||
|
xOpen file object.
|
||||||
|
*/
|
||||||
|
getOFileForSFile(ptr){
|
||||||
return this.#mapSqlite3FileToFile.get(ptr);
|
return this.#mapSqlite3FileToFile.get(ptr);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
Maps or unmaps (if file is falsy) the given (sqlite3_file*)
|
Maps or unmaps (if file is falsy) the given (sqlite3_file*)
|
||||||
to an xOpen file object and to this pool object.
|
to an xOpen file object and to this pool object.
|
||||||
*/
|
*/
|
||||||
setFileForPtr(pFile,file){
|
mapSFileToOFile(pFile,file){
|
||||||
if(file){
|
if(file){
|
||||||
this.#mapSqlite3FileToFile.set(pFile, file);
|
this.#mapSqlite3FileToFile.set(pFile, file);
|
||||||
setPoolForPFile(pFile, this);
|
setPoolForPFile(pFile, this);
|
||||||
@ -746,14 +761,34 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
setPoolForPFile(pFile, false);
|
setPoolForPFile(pFile, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns true if the given client-defined file name is in this
|
||||||
|
object's name-to-SAH map.
|
||||||
|
*/
|
||||||
hasFilename(name){
|
hasFilename(name){
|
||||||
return this.#mapFilenameToSAH.has(name)
|
return this.#mapFilenameToSAH.has(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the SAH associated with the given
|
||||||
|
client-defined file name.
|
||||||
|
*/
|
||||||
getSAHForPath(path){
|
getSAHForPath(path){
|
||||||
return this.#mapFilenameToSAH.get(path);
|
return this.#mapFilenameToSAH.get(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Removes this object's sqlite3_vfs registration and shuts down
|
||||||
|
this object, releasing all handles, mappings, and whatnot,
|
||||||
|
including deleting its data directory. There is currently no
|
||||||
|
way to "revive" the object and reaquire its resources.
|
||||||
|
|
||||||
|
This function is intended primarily for testing.
|
||||||
|
|
||||||
|
Resolves to true if it did its job, false if the
|
||||||
|
VFS has already been shut down.
|
||||||
|
*/
|
||||||
async removeVfs(){
|
async removeVfs(){
|
||||||
if(!this.#cVfs.pointer) return false;
|
if(!this.#cVfs.pointer) return false;
|
||||||
capi.sqlite3_vfs_unregister(this.#cVfs.pointer);
|
capi.sqlite3_vfs_unregister(this.#cVfs.pointer);
|
||||||
@ -773,6 +808,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Documented elsewhere in this file.
|
||||||
exportFile(name){
|
exportFile(name){
|
||||||
const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name);
|
const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name);
|
||||||
const n = sah.getSize() - HEADER_OFFSET_DATA;
|
const n = sah.getSize() - HEADER_OFFSET_DATA;
|
||||||
@ -781,6 +817,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Documented elsewhere in this file.
|
||||||
importDb(name, bytes){
|
importDb(name, bytes){
|
||||||
const n = bytes.byteLength;
|
const n = bytes.byteLength;
|
||||||
if(n<512 || n%512!=0){
|
if(n<512 || n%512!=0){
|
||||||
@ -803,13 +840,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A SAHPoolUtil instance is exposed to clients in order to manipulate an OpfsSAHPool object without directly exposing that
|
A OpfsSAHPoolUtil instance is exposed to clients in order to
|
||||||
|
manipulate an OpfsSAHPool object without directly exposing that
|
||||||
object and allowing for some semantic changes compared to that
|
object and allowing for some semantic changes compared to that
|
||||||
class.
|
class.
|
||||||
|
|
||||||
Class docs are in the client-level docs for installOpfsSAHPoolVfs().
|
Class docs are in the client-level docs for
|
||||||
|
installOpfsSAHPoolVfs().
|
||||||
*/
|
*/
|
||||||
class SAHPoolUtil {
|
class OpfsSAHPoolUtil {
|
||||||
/* This object's associated OpfsSAHPool. */
|
/* This object's associated OpfsSAHPool. */
|
||||||
#p;
|
#p;
|
||||||
|
|
||||||
@ -818,18 +857,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
this.vfsName = sahPool.vfsName;
|
this.vfsName = sahPool.vfsName;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addCapacity(n){
|
async addCapacity(n){ return this.#p.addCapacity(n) }
|
||||||
return this.#p.addCapacity(n);
|
|
||||||
}
|
async reduceCapacity(n){ return this.#p.reduceCapacity(n) }
|
||||||
async reduceCapacity(n){
|
|
||||||
return this.#p.reduceCapacity(n);
|
getCapacity(){ return this.#p.getCapacity(this.#p) }
|
||||||
}
|
|
||||||
getCapacity(){
|
getFileCount(){ return this.#p.getFileCount() }
|
||||||
return this.#p.getCapacity(this.#p);
|
|
||||||
}
|
|
||||||
getFileCount(){
|
|
||||||
return this.#p.getFileCount();
|
|
||||||
}
|
|
||||||
async reserveMinimumCapacity(min){
|
async reserveMinimumCapacity(min){
|
||||||
const c = this.#p.getCapacity();
|
const c = this.#p.getCapacity();
|
||||||
return (c < min) ? this.#p.addCapacity(min - c) : c;
|
return (c < min) ? this.#p.addCapacity(min - c) : c;
|
||||||
@ -839,20 +874,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
|
|
||||||
importDb(name, bytes){ return this.#p.importDb(name,bytes) }
|
importDb(name, bytes){ return this.#p.importDb(name,bytes) }
|
||||||
|
|
||||||
async wipeFiles(){return this.#p.reset(true)}
|
async wipeFiles(){ return this.#p.reset(true) }
|
||||||
|
|
||||||
unlink(filename){
|
unlink(filename){ return this.#p.deletePath(filename) }
|
||||||
return this.#p.deletePath(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
async removeVfs(){return this.#p.removeVfs()}
|
async removeVfs(){ return this.#p.removeVfs() }
|
||||||
|
|
||||||
}/* class SAHPoolUtil */;
|
}/* class OpfsSAHPoolUtil */;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Ensure that the client has a "fully-sync" SAH impl,
|
Returns a resolved Promise if the current environment
|
||||||
else reject the promise. Returns true on success,
|
has a "fully-sync" SAH impl, else a rejected Promise.
|
||||||
throws on error.
|
|
||||||
*/
|
*/
|
||||||
const apiVersionCheck = async ()=>{
|
const apiVersionCheck = async ()=>{
|
||||||
const dh = await navigator.storage.getDirectory();
|
const dh = await navigator.storage.getDirectory();
|
||||||
@ -1087,7 +1119,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
|||||||
return thePool.isReady.then(async()=>{
|
return thePool.isReady.then(async()=>{
|
||||||
/** The poolUtil object will be the result of the
|
/** The poolUtil object will be the result of the
|
||||||
resolved Promise. */
|
resolved Promise. */
|
||||||
const poolUtil = new SAHPoolUtil(thePool);
|
const poolUtil = new OpfsSAHPoolUtil(thePool);
|
||||||
|
|
||||||
if(sqlite3.oo1){
|
if(sqlite3.oo1){
|
||||||
const oo1 = sqlite3.oo1;
|
const oo1 = sqlite3.oo1;
|
||||||
|
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
|||||||
C Update\sthe\sdevelopment-over-ssh\sdocs\sfor\sthe\swasm\sbuild.
|
C More\sinternal\srefactoring\sand\sdocs\sfor\sopfs-sahpool.
|
||||||
D 2023-07-19T17:46:28.936
|
D 2023-07-19T17:47:02.768
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -502,7 +502,7 @@ F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b17386
|
|||||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||||
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.js d3e41757230c8a41fccc4db077d029546f0ebccd13d4ba0111c52ca77779ab70
|
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.js 05b5646b91faa947833d43a840e8b94abb441afa953ee5a11cc7f07f4e01361a
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4946af0d6fbd395aa39966562ca85900664605a5f0cc10fff50146dee527812c
|
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4946af0d6fbd395aa39966562ca85900664605a5f0cc10fff50146dee527812c
|
||||||
F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f
|
F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f
|
||||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
||||||
@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 534481cd0c2e6f62dd0a82f25d4b78fdcc671eb70d6966693c98212a6420891c
|
P 500109bd0a4c134b91c37f397ff1ee828e09c17f7ecd153f975ede748caee7bb
|
||||||
R 3098985ac29097adbc0d24d2b5daf2dc
|
R 44dc85544ec440f7c21f7b899d57ed02
|
||||||
U stephan
|
U stephan
|
||||||
Z 78455e14df71dd2dbc1be007d9b53932
|
Z e1c9bd04ae7a0c44d52816708800bbbb
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
500109bd0a4c134b91c37f397ff1ee828e09c17f7ecd153f975ede748caee7bb
|
64ccf6177a019eab46fb3345ad1e8ba80eaf2c9da55767031f9f04ccd16afb4d
|
Reference in New Issue
Block a user