mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
batch-runner.js: add rudimentary metrics export to CSV. Add a toggle to reverse the log output mode (in normal order or most recent first).
FossilOrigin-Name: b26e2bc05537a1f451db1bdd36a824d71c3ea25a130b6285f31ff9799d65fa7a
This commit is contained in:
@@ -62,11 +62,14 @@ $(dir.top)/sqlite3.c:
|
|||||||
emcc_opt ?= -O0
|
emcc_opt ?= -O0
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release:
|
release:
|
||||||
$(MAKE) 'emcc_opt=-Os -g3'
|
$(MAKE) 'emcc_opt=-Os -g3 -flto'
|
||||||
# ^^^^^ target-specific vars, e.g.:
|
# ^^^^^ target-specific vars, e.g.:
|
||||||
# release: emcc_opt=...
|
# release: emcc_opt=...
|
||||||
# apparently only work for file targets, not PHONY targets?
|
# apparently only work for file targets, not PHONY targets?
|
||||||
#
|
#
|
||||||
|
# ^^^ -flto improves runtime speed at -O0 considerably but doubles
|
||||||
|
# build time.
|
||||||
|
#
|
||||||
# ^^^^ -O3, -Oz, -Os minify symbol names and there appears to be no
|
# ^^^^ -O3, -Oz, -Os minify symbol names and there appears to be no
|
||||||
# way around that except to use -g3, but -g3 causes the binary file
|
# way around that except to use -g3, but -g3 causes the binary file
|
||||||
# size to absolutely explode (approx. 5x larger). This minification
|
# size to absolutely explode (approx. 5x larger). This minification
|
||||||
@@ -284,6 +287,7 @@ endif
|
|||||||
|
|
||||||
CLEAN_FILES += $(sqlite3.js) $(sqlite3.wasm)
|
CLEAN_FILES += $(sqlite3.js) $(sqlite3.wasm)
|
||||||
all: $(sqlite3.js)
|
all: $(sqlite3.js)
|
||||||
|
wasm: $(sqlite3.js)
|
||||||
# End main Emscripten-based module build
|
# End main Emscripten-based module build
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
|
@@ -42,11 +42,16 @@
|
|||||||
<button class='disable-during-eval' id='sql-run'>Run selected SQL</button>
|
<button class='disable-during-eval' id='sql-run'>Run selected SQL</button>
|
||||||
<button class='disable-during-eval' id='sql-run-next'>Run next...</button>
|
<button class='disable-during-eval' id='sql-run-next'>Run next...</button>
|
||||||
<button class='disable-during-eval' id='sql-run-remaining'>Run all remaining...</button>
|
<button class='disable-during-eval' id='sql-run-remaining'>Run all remaining...</button>
|
||||||
|
<button class='disable-during-eval' id='export-metrics'>Export metrics (WIP)</button>
|
||||||
<button class='disable-during-eval' id='db-reset'>Reset db</button>
|
<button class='disable-during-eval' id='db-reset'>Reset db</button>
|
||||||
<button id='output-clear'>Clear output</button>
|
<button id='output-clear'>Clear output</button>
|
||||||
|
<span class='input-wrapper'>
|
||||||
|
<input type='checkbox' class='disable-during-eval' id='cb-reverse-log-order' checked></input>
|
||||||
|
<label for='cb-reverse-log-order'>Reverse log order</label>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div>(Log output is in reverse order, newest first!)</div>
|
<div id='reverse-log-notice' class='hidden'>(Log output is in reverse order, newest first!)</div>
|
||||||
<div id='test-output'></div>
|
<div id='test-output'></div>
|
||||||
|
|
||||||
<script src="sqlite3.js"></script>
|
<script src="sqlite3.js"></script>
|
||||||
@@ -59,13 +64,25 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.warning { color: firebrick; }
|
.warning { color: firebrick; }
|
||||||
|
.input-wrapper {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
#test-output {
|
#test-output {
|
||||||
border: 1px inset;
|
border: 1px inset;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
/*max-height: 30em;*/
|
/*max-height: 30em;*/
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
white-space: break-spaces;
|
white-space: break-spaces;
|
||||||
display: flex; flex-direction: column-reverse;
|
display: flex; flex-direction: column;
|
||||||
|
}
|
||||||
|
#test-output.reverse {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
position: absolute !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -26,10 +26,22 @@
|
|||||||
btnRun: document.querySelector('#sql-run'),
|
btnRun: document.querySelector('#sql-run'),
|
||||||
btnRunNext: document.querySelector('#sql-run-next'),
|
btnRunNext: document.querySelector('#sql-run-next'),
|
||||||
btnRunRemaining: document.querySelector('#sql-run-remaining'),
|
btnRunRemaining: document.querySelector('#sql-run-remaining'),
|
||||||
|
btnExportMetrics: document.querySelector('#export-metrics'),
|
||||||
btnClear: document.querySelector('#output-clear'),
|
btnClear: document.querySelector('#output-clear'),
|
||||||
btnReset: document.querySelector('#db-reset')
|
btnReset: document.querySelector('#db-reset'),
|
||||||
|
cbReverseLog: document.querySelector('#cb-reverse-log-order')
|
||||||
},
|
},
|
||||||
cache:{},
|
cache:{},
|
||||||
|
metrics:{
|
||||||
|
/**
|
||||||
|
Map of sql-file to timing metrics. We currently only store
|
||||||
|
the most recent run of each file, but we really should store
|
||||||
|
all runs so that we can average out certain values which vary
|
||||||
|
significantly across runs. e.g. a mandelbrot-generating query
|
||||||
|
will have a wide range of runtimes when run 10 times in a
|
||||||
|
row.
|
||||||
|
*/
|
||||||
|
},
|
||||||
log: console.log.bind(console),
|
log: console.log.bind(console),
|
||||||
warn: console.warn.bind(console),
|
warn: console.warn.bind(console),
|
||||||
cls: function(){this.e.output.innerHTML = ''},
|
cls: function(){this.e.output.innerHTML = ''},
|
||||||
@@ -63,8 +75,11 @@
|
|||||||
const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
|
const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
|
||||||
const ppDb = wasm.scopedAllocPtr();
|
const ppDb = wasm.scopedAllocPtr();
|
||||||
const rc = capi.sqlite3_open_v2(fn, ppDb, oFlags, null);
|
const rc = capi.sqlite3_open_v2(fn, ppDb, oFlags, null);
|
||||||
if(rc) toss("sqlite3_open_v2() failed with code",rc);
|
|
||||||
pDb = wasm.getPtrValue(ppDb)
|
pDb = wasm.getPtrValue(ppDb)
|
||||||
|
if(rc){
|
||||||
|
if(pDb) capi.sqlite3_close_v2(pDb);
|
||||||
|
toss("sqlite3_open_v2() failed with code",rc);
|
||||||
|
}
|
||||||
}finally{
|
}finally{
|
||||||
wasm.scopedAllocPop(stack);
|
wasm.scopedAllocPop(stack);
|
||||||
}
|
}
|
||||||
@@ -84,6 +99,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads batch-runner.list and populates the selection list from
|
||||||
|
it. Returns a promise which resolves to nothing in particular
|
||||||
|
when it completes. Only intended to be run once at the start
|
||||||
|
of the app.
|
||||||
|
*/
|
||||||
loadSqlList: async function(){
|
loadSqlList: async function(){
|
||||||
const sel = this.e.selSql;
|
const sel = this.e.selSql;
|
||||||
sel.innerHTML = '';
|
sel.innerHTML = '';
|
||||||
@@ -156,7 +177,62 @@
|
|||||||
document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable);
|
document.querySelectorAll('.disable-during-eval').forEach((e)=>e.disabled = disable);
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Fetch ./fn and eval it as an SQL blob. */
|
/**
|
||||||
|
Converts this.metrics() to a form which is suitable for easy conversion to
|
||||||
|
CSV. It returns an array of arrays. The first sub-array is the column names.
|
||||||
|
The 2nd and subsequent are the values, one per test file (only the most recent
|
||||||
|
metrics are kept for any given file).
|
||||||
|
*/
|
||||||
|
metricsToArrays: function(){
|
||||||
|
const rc = [];
|
||||||
|
Object.keys(this.metrics).sort().forEach((k)=>{
|
||||||
|
const m = this.metrics[k];
|
||||||
|
delete m.evalFileStart;
|
||||||
|
delete m.evalFileEnd;
|
||||||
|
const mk = Object.keys(m).sort();
|
||||||
|
if(!rc.length){
|
||||||
|
rc.push(['file', ...mk]);
|
||||||
|
}
|
||||||
|
const row = [k.split('/').pop()/*remove dir prefix from filename*/];
|
||||||
|
rc.push(row);
|
||||||
|
mk.forEach((kk)=>row.push(m[kk]));
|
||||||
|
});
|
||||||
|
return rc;
|
||||||
|
},
|
||||||
|
|
||||||
|
metricsToBlob: function(colSeparator='\t'){
|
||||||
|
const ar = [], ma = this.metricsToArrays();
|
||||||
|
if(!ma.length){
|
||||||
|
this.logErr("Metrics are empty. Run something.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ma.forEach(function(row){
|
||||||
|
ar.push(row.join(colSeparator),'\n');
|
||||||
|
});
|
||||||
|
return new Blob(ar);
|
||||||
|
},
|
||||||
|
|
||||||
|
downloadMetrics: function(){
|
||||||
|
const b = this.metricsToBlob();
|
||||||
|
if(!b) return;
|
||||||
|
const url = URL.createObjectURL(b);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = 'batch-runner-metrics-'+((new Date().getTime()/1000) | 0)+'.csv';
|
||||||
|
this.logHtml("Triggering download of",a.download);
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
setTimeout(()=>{
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fetch file fn and eval it as an SQL blob. This is an async
|
||||||
|
operation and returns a Promise which resolves to this
|
||||||
|
object on success.
|
||||||
|
*/
|
||||||
evalFile: async function(fn){
|
evalFile: async function(fn){
|
||||||
const sql = await this.fetchFile(fn);
|
const sql = await this.fetchFile(fn);
|
||||||
const banner = "========================================";
|
const banner = "========================================";
|
||||||
@@ -165,9 +241,11 @@
|
|||||||
const capi = this.sqlite3.capi, wasm = capi.wasm;
|
const capi = this.sqlite3.capi, wasm = capi.wasm;
|
||||||
let pStmt = 0, pSqlBegin;
|
let pStmt = 0, pSqlBegin;
|
||||||
const stack = wasm.scopedAllocPush();
|
const stack = wasm.scopedAllocPush();
|
||||||
const metrics = Object.create(null);
|
const metrics = this.metrics[fn] = Object.create(null);
|
||||||
metrics.prepTotal = metrics.stepTotal = 0;
|
metrics.prepTotal = metrics.stepTotal = 0;
|
||||||
metrics.stmtCount = 0;
|
metrics.stmtCount = 0;
|
||||||
|
metrics.malloc = 0;
|
||||||
|
metrics.strcpy = 0;
|
||||||
this.blockControls(true);
|
this.blockControls(true);
|
||||||
if(this.gotErr){
|
if(this.gotErr){
|
||||||
this.logErr("Cannot run ["+fn+"]: error cleanup is pending.");
|
this.logErr("Cannot run ["+fn+"]: error cleanup is pending.");
|
||||||
@@ -180,11 +258,16 @@
|
|||||||
let t;
|
let t;
|
||||||
let sqlByteLen = sql.byteLength;
|
let sqlByteLen = sql.byteLength;
|
||||||
const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
|
const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
|
||||||
|
t = performance.now();
|
||||||
pSqlBegin = wasm.alloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
|
pSqlBegin = wasm.alloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
|
||||||
|
metrics.malloc = performance.now() - t;
|
||||||
|
metrics.byteLength = sqlByteLen;
|
||||||
let pSql = pSqlBegin;
|
let pSql = pSqlBegin;
|
||||||
const pSqlEnd = pSqlBegin + sqlByteLen;
|
const pSqlEnd = pSqlBegin + sqlByteLen;
|
||||||
|
t = performance.now();
|
||||||
wasm.heap8().set(sql, pSql);
|
wasm.heap8().set(sql, pSql);
|
||||||
wasm.setMemValue(pSql + sqlByteLen, 0);
|
wasm.setMemValue(pSql + sqlByteLen, 0);
|
||||||
|
metrics.strcpy = performance.now() - t;
|
||||||
let breaker = 0;
|
let breaker = 0;
|
||||||
while(pSql && wasm.getMemValue(pSql,'i8')){
|
while(pSql && wasm.getMemValue(pSql,'i8')){
|
||||||
wasm.setPtrValue(ppStmt, 0);
|
wasm.setPtrValue(ppStmt, 0);
|
||||||
@@ -261,6 +344,20 @@
|
|||||||
}
|
}
|
||||||
this.openDb(dbFile, !!pDir);
|
this.openDb(dbFile, !!pDir);
|
||||||
const who = this;
|
const who = this;
|
||||||
|
const eReverseLogNotice = document.querySelector('#reverse-log-notice');
|
||||||
|
if(this.e.cbReverseLog.checked){
|
||||||
|
eReverseLogNotice.classList.remove('hidden');
|
||||||
|
this.e.output.classList.add('reverse');
|
||||||
|
}
|
||||||
|
this.e.cbReverseLog.addEventListener('change', function(){
|
||||||
|
if(this.checked){
|
||||||
|
who.e.output.classList.add('reverse');
|
||||||
|
eReverseLogNotice.classList.remove('hidden');
|
||||||
|
}else{
|
||||||
|
who.e.output.classList.remove('reverse');
|
||||||
|
eReverseLogNotice.classList.add('hidden');
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
this.e.btnClear.addEventListener('click', ()=>this.cls(), false);
|
this.e.btnClear.addEventListener('click', ()=>this.cls(), false);
|
||||||
this.e.btnRun.addEventListener('click', function(){
|
this.e.btnRun.addEventListener('click', function(){
|
||||||
if(!who.e.selSql.value) return;
|
if(!who.e.selSql.value) return;
|
||||||
@@ -278,6 +375,12 @@
|
|||||||
who.openDb(fn,true);
|
who.openDb(fn,true);
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
this.e.btnExportMetrics.addEventListener('click', function(){
|
||||||
|
who.logHtml2('warning',"Metrics export is a Work in Progress. See output in dev console.");
|
||||||
|
who.downloadMetrics();
|
||||||
|
const m = who.metricsToArrays();
|
||||||
|
console.log("Metrics:",who.metrics, m);
|
||||||
|
});
|
||||||
this.e.btnRunRemaining.addEventListener('click', async function(){
|
this.e.btnRunRemaining.addEventListener('click', async function(){
|
||||||
let v = who.e.selSql.value;
|
let v = who.e.selSql.value;
|
||||||
const timeStart = performance.now();
|
const timeStart = performance.now();
|
||||||
|
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C batch-runner.js:\sre-enable\sunlink-before-run\sso\sthat\sOPFS\sspeedtest1\sbatch\scan\swork.
|
C batch-runner.js:\sadd\srudimentary\smetrics\sexport\sto\sCSV.\sAdd\sa\stoggle\sto\sreverse\sthe\slog\soutput\smode\s(in\snormal\sorder\sor\smost\srecent\sfirst).
|
||||||
D 2022-08-30T10:26:33.223
|
D 2022-08-30T17:57:50.778
|
||||||
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
|
||||||
@@ -474,7 +474,7 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
|||||||
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
|
||||||
F ext/wasm/EXPORTED_FUNCTIONS.fiddle db7a4602f043cf4a5e4135be3609a487f9f1c83f05778bfbdf93766be4541b96
|
F ext/wasm/EXPORTED_FUNCTIONS.fiddle db7a4602f043cf4a5e4135be3609a487f9f1c83f05778bfbdf93766be4541b96
|
||||||
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02
|
F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02
|
||||||
F ext/wasm/GNUmakefile b5d1e285ed9814646e1fb12a27b7507aea2d7208ef76e486e1471c8aabac5226
|
F ext/wasm/GNUmakefile fd1ba419c38d79f742849cc96a1f1e1dd63821e6173bc5727f0a5439f04b4131
|
||||||
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
|
F ext/wasm/README.md e1ee1e7c321c6a250bf78a84ca6f5882890a237a450ba5a0649c7a8399194c52
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77ef4bcf37e362b9ad61f9c175dfc0f1b3e571563fb311b96581cf422ee6a8ec
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 77ef4bcf37e362b9ad61f9c175dfc0f1b3e571563fb311b96581cf422ee6a8ec
|
||||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||||
@@ -489,8 +489,8 @@ F ext/wasm/api/sqlite3-api-prologue.js 2d5c5d3355f55eefe51922cec5bfedbec0f8300db
|
|||||||
F ext/wasm/api/sqlite3-api-worker1.js 73579555563b789785ae83724014eaf31811073aad9be6596c8336ffb51edd71
|
F ext/wasm/api/sqlite3-api-worker1.js 73579555563b789785ae83724014eaf31811073aad9be6596c8336ffb51edd71
|
||||||
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
|
||||||
F ext/wasm/api/sqlite3-wasm.c 0d81282eaeff2a6e9fc5c28a388c5c5b45cf25a9393992fa511ac009b27df982
|
F ext/wasm/api/sqlite3-wasm.c 0d81282eaeff2a6e9fc5c28a388c5c5b45cf25a9393992fa511ac009b27df982
|
||||||
F ext/wasm/batch-runner.html e5c3edd4a6c9359f6d9e6c99cb5f87f09007d98fa1c705ed3efa370abcd4323e
|
F ext/wasm/batch-runner.html 439245594711981831f2775f1426fd20d73a9b1bbf53f2cbbfc1194fa069891c
|
||||||
F ext/wasm/batch-runner.js da471fb7b5c6c918cfe59adaebedc3af24a1268084d09d90143653c71b2493dd
|
F ext/wasm/batch-runner.js dfe194ff87dac20e641aeee7080b74a877ca4a24ea107d6a80ff8115b28b7f0b
|
||||||
F ext/wasm/common/SqliteTestUtil.js eb96275bed43fdb364b7d65bcded0ca5e22aaacff120d593d1385f852f486247
|
F ext/wasm/common/SqliteTestUtil.js eb96275bed43fdb364b7d65bcded0ca5e22aaacff120d593d1385f852f486247
|
||||||
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
|
||||||
F ext/wasm/common/testing.css 572cf1ffae0b6eb7ca63684d3392bf350217a07b90e7a896e4fa850700c989b0
|
F ext/wasm/common/testing.css 572cf1ffae0b6eb7ca63684d3392bf350217a07b90e7a896e4fa850700c989b0
|
||||||
@@ -2013,8 +2013,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 06c106a7d23e4486dbed092757b7588688226ad35539ecc31378a8497f59d1ec
|
P ba08f7a7f12601aa580a8dc493b43cdd5ab65c87d5e4b3fd2f549343e45c2d2a
|
||||||
R 4e67c8f75eba175d0066f0954616ff1b
|
R cd46865d209bc499b87d03a53afeb5f7
|
||||||
U stephan
|
U stephan
|
||||||
Z 9d799461f6bdad041adab908a7c4bd92
|
Z a638c92d95e9388486f91bc003769b2d
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@@ -1 +1 @@
|
|||||||
ba08f7a7f12601aa580a8dc493b43cdd5ab65c87d5e4b3fd2f549343e45c2d2a
|
b26e2bc05537a1f451db1bdd36a824d71c3ea25a130b6285f31ff9799d65fa7a
|
Reference in New Issue
Block a user