forked from mhutchie/vscode-git-graph
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Trigger life cycle events on Git Graph install, update, or uninstall,…
… to allow the extension to utilise the latest features of Visual Studio Code as soon as the majority of users are using a compatible version. Full details are available at: https://api.mhutchie.com/vscode-git-graph/about
- Loading branch information
Showing
8 changed files
with
392 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,18 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const OUTPUT_DIRECTORY = './out'; | ||
const ASKPASS_DIRECTORY = '/askpass'; | ||
|
||
if (fs.existsSync(OUTPUT_DIRECTORY)) { | ||
fs.readdirSync(OUTPUT_DIRECTORY).forEach(filename => { | ||
if (filename !== 'askpass') { | ||
fs.unlinkSync(path.join(OUTPUT_DIRECTORY, filename)); | ||
} | ||
}); | ||
|
||
if (fs.existsSync(OUTPUT_DIRECTORY + ASKPASS_DIRECTORY)) { | ||
fs.readdirSync(OUTPUT_DIRECTORY + ASKPASS_DIRECTORY).forEach(filename => { | ||
fs.unlinkSync(path.join(OUTPUT_DIRECTORY + ASKPASS_DIRECTORY, filename)); | ||
function deleteFolderAndFiles(directory) { | ||
if (fs.existsSync(directory)) { | ||
fs.readdirSync(directory).forEach((filename) => { | ||
const fullPath = path.join(directory, filename); | ||
if (fs.statSync(fullPath).isDirectory()) { | ||
deleteFolderAndFiles(fullPath); | ||
} else { | ||
fs.unlinkSync(fullPath); | ||
} | ||
}); | ||
fs.rmdirSync(directory); | ||
} | ||
} | ||
|
||
deleteFolderAndFiles('./out'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/** | ||
* Git Graph generates an event when it is installed, updated, or uninstalled, that is anonymous, non-personal, and cannot be correlated. | ||
* - Each event only contains the Git Graph and Visual Studio Code version numbers, and a 256 bit cryptographically strong pseudo-random nonce. | ||
* - The two version numbers recorded in these events only allow aggregate compatibility information to be generated (e.g. 50% of users are | ||
* using Visual Studio Code >= 1.41.0). These insights enable Git Graph to utilise the latest features of Visual Studio Code as soon as | ||
* the majority of users are using a compatible version. The data cannot, and will not, be used for any other purpose. | ||
* - Full details are available at: https://api.mhutchie.com/vscode-git-graph/about | ||
*/ | ||
|
||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import * as vscode from 'vscode'; | ||
import { generateNonce, getDataDirectory, getLifeCycleStateInDirectory, LifeCycleStage, LifeCycleState, saveLifeCycleStateInDirectory, sendQueue } from './utils'; | ||
|
||
/** | ||
* Run on startup to detect if Git Graph has been installed or updated, and if so generate an event. | ||
* @param extensionContext The extension context of Git Graph. | ||
*/ | ||
export async function onStartUp(extensionContext: vscode.ExtensionContext) { | ||
if (vscode.env.sessionId === 'someValue.sessionId') { | ||
// Extension is running in the Extension Development Host, don't proceed. | ||
return; | ||
} | ||
|
||
let state = await getLifeCycleStateInDirectory(extensionContext.globalStoragePath); | ||
|
||
if (state !== null && !state.apiAvailable) { | ||
// The API is no longer available, don't proceed. | ||
return; | ||
} | ||
|
||
const versions = { | ||
extension: await getExtensionVersion(extensionContext), | ||
vscode: vscode.version | ||
}; | ||
|
||
if (state === null || state.current.extension !== versions.extension) { | ||
// This is the first startup after installing Git Graph, or Git Graph has been updated since the last startup. | ||
const nonce = await getNonce(); | ||
|
||
if (state === null) { | ||
// Install | ||
state = { | ||
previous: null, | ||
current: versions, | ||
apiAvailable: true, | ||
queue: [{ | ||
stage: LifeCycleStage.Install, | ||
extension: versions.extension, | ||
vscode: versions.vscode, | ||
nonce: nonce | ||
}] | ||
}; | ||
} else { | ||
// Update | ||
state.previous = state.current; | ||
state.current = versions; | ||
state.queue.push({ | ||
stage: LifeCycleStage.Update, | ||
from: state.previous, | ||
to: state.current, | ||
nonce: nonce | ||
}); | ||
} | ||
|
||
await saveLifeCycleState(extensionContext, state); | ||
state.apiAvailable = await sendQueue(state.queue); | ||
state.queue = []; | ||
await saveLifeCycleState(extensionContext, state); | ||
|
||
} else if (state.queue.length > 0) { | ||
// There are one or more events in the queue that previously failed to send, send them | ||
state.apiAvailable = await sendQueue(state.queue); | ||
state.queue = []; | ||
await saveLifeCycleState(extensionContext, state); | ||
} | ||
} | ||
|
||
/** | ||
* Saves the life cycle state to the extensions global storage directory (for use during future updates), | ||
* and to a directory in this Git Graph installation (for use during future uninstalls). | ||
* @param extensionContext The extension context of Git Graph. | ||
* @param state The state to save. | ||
*/ | ||
function saveLifeCycleState(extensionContext: vscode.ExtensionContext, state: LifeCycleState) { | ||
return Promise.all([ | ||
saveLifeCycleStateInDirectory(extensionContext.globalStoragePath, state), | ||
saveLifeCycleStateInDirectory(getDataDirectory(), state) | ||
]); | ||
} | ||
|
||
/** | ||
* Gets the version of Git Graph. | ||
* @param extensionContext The extension context of Git Graph. | ||
* @returns The Git Graph version. | ||
*/ | ||
function getExtensionVersion(extensionContext: vscode.ExtensionContext) { | ||
return new Promise<string>((resolve, reject) => { | ||
fs.readFile(path.join(extensionContext.extensionPath, 'package.json'), (err, data) => { | ||
if (err) { | ||
reject(); | ||
} else { | ||
try { | ||
resolve(JSON.parse(data.toString()).version); | ||
} catch (_) { | ||
reject(); | ||
} | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
/** | ||
* Get a nonce generated for this installation of Git Graph. | ||
* @returns A 256 bit cryptographically strong pseudo-random nonce. | ||
*/ | ||
function getNonce() { | ||
return new Promise<string>((resolve, reject) => { | ||
const dir = getDataDirectory(); | ||
const file = path.join(dir, 'lock.json'); | ||
fs.mkdir(dir, (err) => { | ||
if (err) { | ||
if (err.code === 'EEXIST') { | ||
// The directory already exists, attempt to read the previously created data | ||
fs.readFile(file, (err, data) => { | ||
if (err) { | ||
// Unable to read the file, reject | ||
reject(); | ||
} else { | ||
try { | ||
// Resolve to the previously generated nonce | ||
resolve(JSON.parse(data.toString()).nonce); | ||
} catch (_) { | ||
reject(); | ||
} | ||
} | ||
}); | ||
} else { | ||
// An unexpected error occurred, reject | ||
reject(); | ||
} | ||
} else { | ||
// The directory was created, generate a nonce | ||
const nonce = generateNonce(); | ||
fs.writeFile(file, JSON.stringify({ nonce: nonce }), (err) => { | ||
if (err) { | ||
// Unable to save data | ||
reject(); | ||
} else { | ||
// Nonce successfully saved, resolve to it | ||
resolve(nonce); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Git Graph generates an event when it is installed, updated, or uninstalled, that is anonymous, non-personal, and cannot be correlated. | ||
* - Each event only contains the Git Graph and Visual Studio Code version numbers, and a 256 bit cryptographically strong pseudo-random nonce. | ||
* - The two version numbers recorded in these events only allow aggregate compatibility information to be generated (e.g. 50% of users are | ||
* using Visual Studio Code >= 1.41.0). These insights enable Git Graph to utilise the latest features of Visual Studio Code as soon as | ||
* the majority of users are using a compatible version. The data cannot, and will not, be used for any other purpose. | ||
* - Full details are available at: https://api.mhutchie.com/vscode-git-graph/about | ||
*/ | ||
|
||
import { generateNonce, getDataDirectory, getLifeCycleStateInDirectory, LifeCycleStage, sendQueue } from './utils'; | ||
|
||
(async function () { | ||
try { | ||
const state = await getLifeCycleStateInDirectory(getDataDirectory()); | ||
if (state !== null) { | ||
if (state.apiAvailable) { | ||
state.queue.push({ | ||
stage: LifeCycleStage.Uninstall, | ||
extension: state.current.extension, | ||
vscode: state.current.vscode, | ||
nonce: generateNonce() | ||
}); | ||
await sendQueue(state.queue); | ||
} | ||
} | ||
} catch (_) { } | ||
})(); |
Oops, something went wrong.