diff --git a/src/service/github.service.ts b/src/service/github.service.ts index c9c2221d..bcfa17d3 100644 --- a/src/service/github.service.ts +++ b/src/service/github.service.ts @@ -184,6 +184,21 @@ export class GitHubService { return gistObject; } + public UpdateChangedFiles( + gistObject: any, + files: File[], + deletedFileNames: string[] + ): any { + gistObject.data.files = {}; + gistObject.data = this.AddFile(files, gistObject.data); + + for (const fileName of deletedFileNames) { + gistObject.data.files[fileName] = null; + } + + return gistObject; + } + public async SaveGIST(gistObject: any): Promise { gistObject.gist_id = gistObject.id; // tslint:disable-next-line:comment-format diff --git a/src/sync.ts b/src/sync.ts index 3e926481..afd097bc 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -228,6 +228,7 @@ export class Sync { let completed: boolean = false; let newGIST: boolean = false; + let uploadedSettingFiles: File[] = allSettingFiles; try { if (syncSetting.gist == null || syncSetting.gist === "") { if (customSettings.askGistDescription) { @@ -284,23 +285,39 @@ export class Sync { localConfig.publicGist = true; } - if ( - !allSettingFiles.some(fileToUpload => { - if (fileToUpload.gistName === "cloudSettings") { + const cloudSettingsFile = allSettingFiles.find( + fileToUpload => fileToUpload.gistName === "cloudSettings" + ); + const changedSettingFiles = allSettingFiles.filter(fileToUpload => { + if (fileToUpload.gistName === "cloudSettings") { + return false; + } + if (!gistObj.data.files[fileToUpload.gistName]) { + return true; + } + if ( + gistObj.data.files[fileToUpload.gistName].content !== + fileToUpload.content + ) { + console.info(`Sync: file ${fileToUpload.gistName} has changed`); + return true; + } + return false; + }); + const deletedGistFileNames = Object.keys(gistObj.data.files).filter( + gistFileName => { + if (gistFileName.startsWith("keybindings")) { return false; } - if (!gistObj.data.files[fileToUpload.gistName]) { - return true; - } - if ( - gistObj.data.files[fileToUpload.gistName].content !== - fileToUpload.content - ) { - console.info(`Sync: file ${fileToUpload.gistName} has changed`); - return true; - } - }) - ) { + return !allSettingFiles.some( + fileToUpload => fileToUpload.gistName === gistFileName + ); + } + ); + const hasSettingChanges = + changedSettingFiles.length > 0 || deletedGistFileNames.length > 0; + + if (!hasSettingChanges) { // Gist files are the same as the local files. if (!localConfig.extConfig.forceUpload) { vscode.window.setStatusBarMessage( @@ -359,7 +376,18 @@ export class Sync { 3000 ); - gistObj = github.UpdateGIST(gistObj, allSettingFiles); + if (!newGIST && !localConfig.extConfig.forceUpload) { + uploadedSettingFiles = cloudSettingsFile + ? [...changedSettingFiles, cloudSettingsFile] + : changedSettingFiles; + gistObj = github.UpdateChangedFiles( + gistObj, + uploadedSettingFiles, + deletedGistFileNames + ); + } else { + gistObj = github.UpdateGIST(gistObj, allSettingFiles); + } completed = await github.SaveGIST(gistObj.data); if (!completed) { vscode.window.showErrorMessage( @@ -396,7 +424,7 @@ export class Sync { if (!syncSetting.quietSync) { state.commons.ShowSummaryOutput( true, - allSettingFiles, + uploadedSettingFiles, null, uploadedExtensions, ignoredExtensions, diff --git a/test/service/githubService/githubService.test.ts b/test/service/githubService/githubService.test.ts new file mode 100644 index 00000000..be27d2e3 --- /dev/null +++ b/test/service/githubService/githubService.test.ts @@ -0,0 +1,63 @@ +import { expect } from "chai"; + +import { File } from "../../../src/service/file.service"; +import { GitHubService } from "../../../src/service/github.service"; + +describe("GitHubService", () => { + it("should update only changed files", () => { + const github: GitHubService = Object.create(GitHubService.prototype); + const gistObject = { + data: { + files: { + "extensions.json": { + content: "unchanged" + }, + "settings.json": { + content: "old" + } + } + } + }; + + const actual = github.UpdateChangedFiles( + gistObject, + [new File("settings.json", "new", "", "settings.json")], + [] + ); + + expect(actual.data.files).to.deep.equals({ + "settings.json": { + content: "new" + } + }); + }); + + it("should preserve explicit gist deletions", () => { + const github: GitHubService = Object.create(GitHubService.prototype); + const gistObject = { + data: { + files: { + "extensions.json": { + content: "old" + }, + "settings.json": { + content: "old" + } + } + } + }; + + const actual = github.UpdateChangedFiles( + gistObject, + [new File("settings.json", "new", "", "settings.json")], + ["extensions.json"] + ); + + expect(actual.data.files).to.deep.equals({ + "extensions.json": null, + "settings.json": { + content: "new" + } + }); + }); +});