Skip to content

Commit

Permalink
Merge pull request #32765 from joaomoreno/uninstall-telemetry
Browse files Browse the repository at this point in the history
Uninstall telemetry
  • Loading branch information
joaomoreno authored Aug 18, 2017
2 parents bb55f06 + 40145f5 commit d45ce51
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,17 @@ export interface IQueryOptions {
sortOrder?: SortOrder;
}

export enum StatisticType {
Uninstall = 'uninstall'
}

export interface IExtensionGalleryService {
_serviceBrand: any;
isEnabled(): boolean;
getRequestHeaders(): TPromise<{ [key: string]: string; }>;
query(options?: IQueryOptions): TPromise<IPager<IGalleryExtension>>;
download(extension: IGalleryExtension): TPromise<string>;
reportStatistic(publisher: string, name: string, version: string, type: StatisticType): TPromise<void>;
getReadme(extension: IGalleryExtension): TPromise<string>;
getManifest(extension: IGalleryExtension): TPromise<IExtensionManifest>;
getChangelog(extension: IGalleryMetadata): TPromise<string>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import * as uuid from 'vs/base/common/uuid';
import { distinct } from 'vs/base/common/arrays';
import { getErrorMessage } from 'vs/base/common/errors';
import { IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement';
import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { assign, getOrDefault } from 'vs/base/common/objects';
import { IRequestService } from 'vs/platform/request/node/request';
Expand Down Expand Up @@ -385,6 +385,27 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
return { galleryExtensions, total };
}

async reportStatistic(publisher: string, name: string, version: string, type: StatisticType): TPromise<void> {
if (!this.isEnabled()) {
return;
}

try {
const headers = {
...await this.commonHTTPHeaders,
Accept: '*/*;api-version=4.0-preview.1'
};

await this.requestService.request({
type: 'POST',
url: this.api(`/publishers/${publisher}/extensions/${name}/${version}/stats?statType=${type}`),
headers
});
} catch (err) {
// noop
}
}

download(extension: IGalleryExtension): TPromise<string> {
return this.loadCompatibleVersion(extension).then(extension => {
const zipPath = path.join(tmpdir(), uuid.generateUuid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import { assign } from 'vs/base/common/objects';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { flatten, distinct } from 'vs/base/common/arrays';
import { extract, buffer } from 'vs/base/node/zip';
import { Promise, TPromise } from 'vs/base/common/winjs.base';
import { TPromise } from 'vs/base/common/winjs.base';
import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension,
IGalleryExtension, IExtensionManifest, IGalleryMetadata,
InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, LocalExtensionType
InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, LocalExtensionType,
StatisticType
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { getLocalExtensionIdFromGallery, getLocalExtensionIdFromManifest, getGalleryExtensionIdFromLocal, getIdAndVersionFromLocalExtensionId, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { localizeManifest } from '../common/extensionNls';
Expand Down Expand Up @@ -223,9 +224,9 @@ export class ExtensionManagementService implements IExtensionManagementService {
}

private rollback(localExtension: ILocalExtension, dependecies: IGalleryExtension[]): TPromise<void> {
return this.doUninstall(localExtension.id)
return this.doUninstall(localExtension)
.then(() => this.filterOutUninstalled(dependecies))
.then(installed => TPromise.join(installed.map((i) => this.doUninstall(i.id))))
.then(installed => TPromise.join(installed.map((i) => this.doUninstall(i))))
.then(() => null);
}

Expand Down Expand Up @@ -304,11 +305,11 @@ export class ExtensionManagementService implements IExtensionManagementService {
}

private checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[], force: boolean): TPromise<void> {
return this.preUninstallExtension(extension.id)
return this.preUninstallExtension(extension)
.then(() => this.hasDependencies(extension, installed) ? this.promptForDependenciesAndUninstall(extension, installed, force) : this.promptAndUninstall(extension, installed, force))
.then(() => this.postUninstallExtension(extension.id),
.then(() => this.postUninstallExtension(extension),
error => {
this.postUninstallExtension(extension.id, error);
this.postUninstallExtension(extension, error);
return TPromise.wrapError(error);
});
}
Expand Down Expand Up @@ -370,7 +371,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
if (dependents.length) {
return TPromise.wrapError<void>(new Error(this.getDependentsErrorMessage(extension, dependents)));
}
return TPromise.join([this.uninstallExtension(extension.id), ...dependenciesToUninstall.map(d => this.doUninstall(d.id))]).then(() => null);
return TPromise.join([this.uninstallExtension(extension.id), ...dependenciesToUninstall.map(d => this.doUninstall(d))]).then(() => null);
}

private getDependentsErrorMessage(extension: ILocalExtension, dependents: ILocalExtension[]): string {
Expand Down Expand Up @@ -419,21 +420,21 @@ export class ExtensionManagementService implements IExtensionManagementService {
return installed.filter(e => e.manifest.extensionDependencies && e.manifest.extensionDependencies.indexOf(getGalleryExtensionIdFromLocal(extension)) !== -1);
}

private doUninstall(id: string): TPromise<void> {
return this.preUninstallExtension(id)
.then(() => this.uninstallExtension(id))
.then(() => this.postUninstallExtension(id),
private doUninstall(extension: ILocalExtension): TPromise<void> {
return this.preUninstallExtension(extension)
.then(() => this.uninstallExtension(extension.id))
.then(() => this.postUninstallExtension(extension),
error => {
this.postUninstallExtension(id, error);
this.postUninstallExtension(extension, error);
return TPromise.wrapError(error);
});
}

private preUninstallExtension(id: string): TPromise<void> {
const extensionPath = path.join(this.extensionsPath, id);
private preUninstallExtension(extension: ILocalExtension): TPromise<void> {
const extensionPath = path.join(this.extensionsPath, extension.id);
return pfs.exists(extensionPath)
.then(exists => exists ? null : TPromise.wrapError(new Error(nls.localize('notExists', "Could not find extension"))))
.then(() => this._onUninstallExtension.fire(id));
.then(() => this._onUninstallExtension.fire(extension.id));
}

private uninstallExtension(id: string): TPromise<void> {
Expand All @@ -443,8 +444,12 @@ export class ExtensionManagementService implements IExtensionManagementService {
.then(() => this.unsetObsolete(id));
}

private postUninstallExtension(id: string, error?: any): TPromise<void> {
return this._onDidUninstallExtension.fire({ id, error });
private async postUninstallExtension(extension: ILocalExtension, error?: any): TPromise<void> {
if (!error) {
await this.galleryService.reportStatistic(extension.manifest.publisher, extension.manifest.name, extension.manifest.version, StatisticType.Uninstall);
}

this._onDidUninstallExtension.fire({ id: extension.id, error });
}

getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> {
Expand Down Expand Up @@ -476,7 +481,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
const limiter = new Limiter(10);

return this.scanExtensionFolders(root)
.then(extensionIds => Promise.join(extensionIds.map(id => {
.then(extensionIds => TPromise.join(extensionIds.map(id => {
const extensionPath = path.join(root, id);

const each = () => pfs.readdir(extensionPath).then(children => {
Expand Down

0 comments on commit d45ce51

Please sign in to comment.