Skip to content

Commit

Permalink
Don't add or remove XML declarations to/from first line of project fi…
Browse files Browse the repository at this point in the history
…les (closes #29) (#30)
  • Loading branch information
jmrog committed Nov 18, 2017
1 parent 1c5d495 commit 0d7e1d6
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 14 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,9 @@
# Change Log
All notable changes to the "vscode-nuget-package-manager" extension will be documented in this file.

## [1.1.5] - 2017-11-17
- Cross-platform team development aid: don't add or remove XML declarations to/from first line of project files (closes #29)

## [1.1.4] - 2017-06-24
- Respect http.proxyStrictSSL setting

Expand Down
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -32,6 +32,9 @@ at the moment, but the eventual plan is to replace this dependency.

## Release Notes

## 1.1.5
- Cross-platform team development aid: don't add or remove XML declarations to/from first line of project files (closes #29)

### 1.1.4
- Respect http.proxyStrictSSL setting

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-nuget-package-manager",
"displayName": "NuGet Package Manager",
"description": "Add or remove .NET Core 1.1+ package references to/from your project's .csproj or .fsproj file using Code's Command Palette.",
"version": "1.1.4",
"version": "1.1.5",
"publisher": "jmrog",
"author": "Jason Rogers <jason@jmichaelrogers.com>",
"license": "MIT",
Expand Down
3 changes: 2 additions & 1 deletion src/actions/add-methods/handleVersionsQuickPick.ts
Expand Up @@ -47,7 +47,8 @@ export default function handleVersionsQuickPick({ selectedVersion, selectedPacka
pickedProjFile,
contents,
selectedPackageName,
selectedVersion
selectedVersion,
originalContents: data
});
});
});
Expand Down
15 changes: 11 additions & 4 deletions src/actions/add-methods/writeFile.ts
Expand Up @@ -2,9 +2,7 @@ import * as fs from 'fs';
import * as vscode from 'vscode';
import { Builder as XMLBuilder } from 'xml2js';

import { handleError, getProjFileExtension } from '../../utils';

const xmlBuilder = new XMLBuilder();
import { handleError, getProjFileExtension, isHeadlessXML } from '../../utils';

const getErrorMessage = (pickedProjFile: string): string => {
const extension = getProjFileExtension(pickedProjFile);
Expand All @@ -13,8 +11,17 @@ const getErrorMessage = (pickedProjFile: string): string => {
return `Failed to write an updated ${fileDescription} file. Please try again later.`;
};

export default function writeFile({ pickedProjFile, contents, selectedPackageName, selectedVersion }): Promise<string | never> {
export default function writeFile({
pickedProjFile,
contents,
selectedPackageName,
selectedVersion,
originalContents = ''
}): Promise<string | never> {
return new Promise((resolve, reject) => {
const xmlBuilder = new XMLBuilder({
headless: isHeadlessXML(originalContents)
});
let xml;

try {
Expand Down
15 changes: 11 additions & 4 deletions src/actions/remove-methods/deletePackageReference.ts
@@ -1,18 +1,22 @@
import * as fs from 'fs';
import { Builder as XMLBuilder } from 'xml2js';

import { handleError, getProjFileExtension } from '../../utils';
import { handleError, getProjFileExtension, isHeadlessXML } from '../../utils';
import { CANCEL } from '../../constants';

const xmlBuilder = new XMLBuilder();

const getErrorMessage = (projFileFullPath: string): string => {
const extension = getProjFileExtension(projFileFullPath);
const fileDescription = extension ? `.${extension}` : 'project';
return `Failed to write an updated ${fileDescription} file. Please try again later.`;
}

export default function deletePackageReference({ projFileFullPath, selectedPackage, parsed, packageRefSection }: any): Promise<string> | Promise<never> {
export default function deletePackageReference({
projFileFullPath,
selectedPackage,
parsed,
packageRefSection,
originalContents = ''
}: any): Promise<string> | Promise<never> {
if (!selectedPackage) {
// Search canceled.
return Promise.reject(CANCEL);
Expand All @@ -33,6 +37,9 @@ export default function deletePackageReference({ projFileFullPath, selectedPacka
itemGroup.splice(packageRefSectionIdx, 1);
}

const xmlBuilder = new XMLBuilder({
headless: isHeadlessXML(originalContents)
});
let xml;

try {
Expand Down
8 changes: 7 additions & 1 deletion src/actions/remove-methods/readInstalledPackages.ts
Expand Up @@ -45,7 +45,13 @@ export default function readInstalledPackages(projFileFullPath: string): Promise

const installedPackages = packageRefSection.PackageReference.map((ref) => `${ref.$.Include} ${ref.$.Version}`);

return resolve({ projFileFullPath, installedPackages, packageRefSection, parsed });
return resolve({
projFileFullPath,
installedPackages,
packageRefSection,
parsed,
originalContents: data
});
});
});
});
Expand Down
16 changes: 14 additions & 2 deletions src/actions/remove-methods/showPackagesQuickPick.ts
@@ -1,6 +1,18 @@
import * as vscode from 'vscode';

export default function showPackagesQuickPick({ projFileFullPath, installedPackages, packageRefSection, parsed }: any): Thenable<any> {
export default function showPackagesQuickPick({
projFileFullPath,
installedPackages,
packageRefSection,
parsed,
originalContents
}: any): Thenable<any> {
return vscode.window.showQuickPick(installedPackages)
.then((selectedPackage: string | undefined) => ({ projFileFullPath, selectedPackage, parsed, packageRefSection }));
.then((selectedPackage: string | undefined) => ({
projFileFullPath,
selectedPackage,
parsed,
packageRefSection,
originalContents
}));
}
4 changes: 3 additions & 1 deletion src/utils/index.ts
Expand Up @@ -3,11 +3,13 @@ import isPlainObject from './isPlainObject';
import flattenNestedArray from './flattenNestedArray';
import getProjFileExtension from './getProjFileExtension';
import getFetchOptions from './getFetchOptions';
import isHeadlessXML from './isHeadlessXML';

export {
handleError,
isPlainObject,
flattenNestedArray,
getProjFileExtension,
getFetchOptions
getFetchOptions,
isHeadlessXML
};
8 changes: 8 additions & 0 deletions src/utils/isHeadlessXML.ts
@@ -0,0 +1,8 @@
const xmlDeclarationStart = '<?xml ';

// NOTE: This method obviously does not check if the file actually is validly formatted XML. That
// much is assumed. What's not assumed is that the first line is an XML declaration, which is what
// this checks for. Good enough to close #29.
export default function isHeadlessXML(candidateXML = '') {
return candidateXML.slice(0, 6).toLowerCase() !== xmlDeclarationStart;
}
2 changes: 2 additions & 0 deletions test/extension.test.ts
@@ -1,6 +1,7 @@
import runFlattenNestedArrayTests from './utils/flattenNestedArray.test';
import runGetProjFileExtensionTests from './utils/getProjFileExtension.test';
import runGetFetchOptionsTests from './utils/getFetchOptions.test';
import runIsHeadlessXMLTests from './utils/isHeadlessXML.test';

import runCreateUpdatedProjectJsonTests from './actions/shared/createUpdatedProjectJson.test';
import runHandleSearchResponseTests from './actions/add-methods/handleSearchResponse.test';
Expand All @@ -9,6 +10,7 @@ import runTruncateProjFilePathTests from './actions/shared/truncateProjFilePath.
runFlattenNestedArrayTests();
runGetProjFileExtensionTests();
runGetFetchOptionsTests();
runIsHeadlessXMLTests();
runCreateUpdatedProjectJsonTests();
runHandleSearchResponseTests();
runTruncateProjFilePathTests();
16 changes: 16 additions & 0 deletions test/utils/isHeadlessXML.test.ts
@@ -0,0 +1,16 @@
import * as expect from 'expect';
import { isHeadlessXML } from '../../src/utils';

export default function runIsHeadlessXMLTests() {
describe('isHeadlessXML', function () {
it('should return false only if the candidate string starts with \'<?xml \'', function () {
expect(isHeadlessXML('')).toBe(true);
expect(isHeadlessXML('some <?xml ')).toBe(true);
expect(isHeadlessXML(' <?xml version="1.0" encoding="UTF-8" standalone="no" ?>')).toBe(true);
expect(isHeadlessXML('<?xml')).toBe(true);
expect(isHeadlessXML('<? xml')).toBe(true);
expect(isHeadlessXML('<?xml ')).toBe(false); // this is ok; the utility assumes it's being given something "XML-like enough"
expect(isHeadlessXML('<?xml version="1.0" encoding="UTF-8" standalone="no" ?>')).toBe(false);
});
});
}

0 comments on commit 0d7e1d6

Please sign in to comment.