Skip to content

Commit

Permalink
Merge pull request #458 from forcedotcom/sh/compare-encoded-filenames
Browse files Browse the repository at this point in the history
fix: match and update maxRevision entries with decoded keys
  • Loading branch information
shetzel authored Aug 21, 2023
2 parents f2b2737 + 3d62d11 commit 1ccea04
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 18 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@
"dependencies": {
"@salesforce/core": "^5.2.0",
"@salesforce/kit": "^3.0.9",
"@salesforce/source-deploy-retrieve": "^9.7.2",
"@salesforce/source-deploy-retrieve": "^9.7.6",
"@salesforce/ts-types": "^2.0.6",
"fast-xml-parser": "^4.2.5",
"graceful-fs": "^4.2.11",
"isomorphic-git": "1.23.0",
"ts-retry-promise": "^0.7.0"
},
"devDependencies": {
"@salesforce/cli-plugins-testkit": "^4.2.9",
"@salesforce/cli-plugins-testkit": "^4.3.0",
"@salesforce/dev-config": "^4.0.1",
"@salesforce/dev-scripts": "^5.5.0",
"@salesforce/prettier-config": "^0.0.3",
Expand Down
4 changes: 3 additions & 1 deletion src/shared/populateFilePaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ export const populateFilePaths = (elements: ChangeResult[], packageDirPaths: str
matchingComponent.xml
} and maybe ${matchingComponent.walkContent().toString()}`
);
const key = getMetadataKey(matchingComponent.type.name, matchingComponent.fullName);
// Decode the key since local components can have encoded fullNames, but results from querying
// SourceMembers have fullNames that are not encoded. See: https://github.com/forcedotcom/cli/issues/1683
const key = decodeURIComponent(getMetadataKey(matchingComponent.type.name, matchingComponent.fullName));
elementMap.set(key, {
...elementMap.get(key),
modified: true,
Expand Down
34 changes: 32 additions & 2 deletions src/shared/remoteSourceTrackingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,18 @@ export class RemoteSourceTrackingService extends ConfigFile<RemoteSourceTracking

// Return a tracked element as MemberRevision data.
private getSourceMember(key: string): Optional<MemberRevision> {
return this.getSourceMembers()[key];
const sourceMembers = this.getSourceMembers();
return (
sourceMembers[key] ?? sourceMembers[getDecodedKeyIfSourceMembersHas({ sourceMembers, key, logger: this.logger })]
);
}

private setMemberRevision(key: string, sourceMember: MemberRevision): void {
this.getContents().sourceMembers[key] = sourceMember;
const sourceMembers = this.getSourceMembers();
const matchingKey = sourceMembers[key]
? key
: getDecodedKeyIfSourceMembersHas({ sourceMembers, key, logger: this.logger });
this.getContents().sourceMembers[matchingKey] = sourceMember;
}

private calculateTimeout(memberCount: number): Duration {
Expand Down Expand Up @@ -588,3 +595,26 @@ const convertRevisionToChange = (memberKey: string, memberRevision: MemberRevisi
name: memberKey.replace(`${memberRevision.memberType}__`, ''),
deleted: memberRevision.isNameObsolete,
});

/**
*
* iterate SourceMember keys and compare their decoded value with the decoded key.
* if there's a match, return the matching decoded key, otherwise, return the original key
*/
function getDecodedKeyIfSourceMembersHas({
key,
sourceMembers,
logger,
}: {
sourceMembers: Dictionary<MemberRevision>;
key: string;
logger: Logger;
}): string {
const originalKeyDecoded = decodeURIComponent(key);
const match = Object.keys(sourceMembers).find((memberKey) => decodeURIComponent(memberKey) === originalKeyDecoded);
if (match) {
logger.debug(`${match} matches already tracked member: ${key}`);
return match;
}
return key;
}
148 changes: 148 additions & 0 deletions test/unit/remoteSourceTracking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,154 @@ describe('remoteSourceTrackingService', () => {
deleted: true,
});
});

it('will match decoded SourceMember keys on get', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1.1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore getSourceMember is private
expect(remoteSourceTrackingService.getSourceMember('Layout__Broker__c-v1%2E1 Broker Layout')).to.deep.equal({
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
});
});

it('will match encoded SourceMember keys on get', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1%2E1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore getSourceMember is private
expect(remoteSourceTrackingService.getSourceMember('Layout__Broker__c-v1.1 Broker Layout')).to.deep.equal({
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
});
});

it('will match/update decoded SourceMember keys on set', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1.1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore setMemberRevision is private
remoteSourceTrackingService.setMemberRevision('Layout__Broker__c-v1%2E1 Broker Layout', {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
});

// @ts-ignore getSourceMembers is private
expect(remoteSourceTrackingService.getSourceMembers()).to.deep.equal({
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1.1 Broker Layout': {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
},
});
});

it('will match/update encoded SourceMember keys on set', async () => {
const maxJson = {
serverMaxRevisionCounter: 2,
sourceMembers: {
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1%2E1 Broker Layout': {
serverRevisionCounter: 2,
lastRetrievedFromServer: 2,
memberType: 'Layout',
isNameObsolete: false,
},
},
};
await remoteSourceTrackingService.setContentsFromObject(maxJson);

// @ts-ignore setMemberRevision is private
remoteSourceTrackingService.setMemberRevision('Layout__Broker__c-v1.1 Broker Layout', {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
});

// @ts-ignore getSourceMembers is private
expect(remoteSourceTrackingService.getSourceMembers()).to.deep.equal({
'Layout__Broker__c-Broker Layout': {
serverRevisionCounter: 1,
lastRetrievedFromServer: 1,
memberType: 'Layout',
isNameObsolete: false,
},
'Layout__Broker__c-v1%2E1 Broker Layout': {
serverRevisionCounter: 3,
lastRetrievedFromServer: 3,
memberType: 'Layout',
isNameObsolete: false,
},
});
});
});

describe('setServerMaxRevision', () => {
Expand Down
61 changes: 48 additions & 13 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -547,14 +547,14 @@
mv "~2"
safe-json-stringify "~1"

"@salesforce/cli-plugins-testkit@^4.2.9":
version "4.2.9"
resolved "https://registry.yarnpkg.com/@salesforce/cli-plugins-testkit/-/cli-plugins-testkit-4.2.9.tgz#813bbb6a7926d17d5d0becd664e08f1c115680d1"
integrity sha512-v71dFmhlgwtmehK2QJ8+toeCYc39WQFu7R2wmhsHQeVA1UuYcx3uue5JnC392PIXddxQtjdR6eazk52tQg4nyA==
"@salesforce/cli-plugins-testkit@^4.3.0":
version "4.3.0"
resolved "https://registry.yarnpkg.com/@salesforce/cli-plugins-testkit/-/cli-plugins-testkit-4.3.0.tgz#253079d476569fbc4977c8100b3bf201b3e4a788"
integrity sha512-kW59i4muO49evQ76waWTfDUXpTfyBUQ0N1QIF4ZFB+aSAdVGG5N/oTMYz882ScS/SwB0XP0H119wT4cLoJI+Mw==
dependencies:
"@salesforce/core" "^5.2.0"
"@salesforce/kit" "^3.0.9"
"@salesforce/ts-types" "^2.0.2"
"@salesforce/ts-types" "^2.0.6"
"@types/shelljs" "^0.8.12"
debug "^4.3.1"
jszip "^3.10.1"
Expand Down Expand Up @@ -607,6 +607,29 @@
proper-lockfile "^4.1.2"
ts-retry-promise "^0.7.0"

"@salesforce/core@^5.2.1":
version "5.2.1"
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-5.2.1.tgz#299bddae7d0705c773b194be8994e5730735e2b4"
integrity sha512-QMx11A0KA/Vl+Ckmz83cw+fiUCMOmsUD8CA3987wAkfJOgxtqyhT4R1R8tj7ad8flQydKUyL3o4UE/2u82tXOw==
dependencies:
"@salesforce/kit" "^3.0.9"
"@salesforce/schemas" "^1.6.0"
"@salesforce/ts-types" "^2.0.5"
"@types/semver" "^7.5.0"
ajv "^8.12.0"
change-case "^4.1.2"
faye "^1.4.0"
form-data "^4.0.0"
js2xmlparser "^4.0.1"
jsforce "^2.0.0-beta.27"
jsonwebtoken "9.0.1"
jszip "3.10.1"
pino "^8.14.2"
pino-abstract-transport "^1.0.0"
pino-pretty "^10.2.0"
proper-lockfile "^4.1.2"
ts-retry-promise "^0.7.0"

"@salesforce/dev-config@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@salesforce/dev-config/-/dev-config-4.0.1.tgz#662ffaa4409713553aaf68eed93e7d2429c3ff0e"
Expand Down Expand Up @@ -669,16 +692,16 @@
resolved "https://registry.yarnpkg.com/@salesforce/schemas/-/schemas-1.6.0.tgz#14505ebad2fb2d4f7b14837545d662766d293561"
integrity sha512-SwhDTLucj/GRbPpxlEoDZeqlX22o+G6fiebTXTu1cZKmd1oE0W2L7SlTTgJnWck8bhTeBIgQi9cpD8c2t5ISKA==

"@salesforce/source-deploy-retrieve@^9.7.2":
version "9.7.2"
resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-9.7.2.tgz#b04b946ea226b21971f4cb94337ab6d8c2cd8b9f"
integrity sha512-RJUSjeNgIpijT0BFEEnEsbOCbkWo7AJaWIN5IHyTzBlExNnTfnze3zq5hOvhuzu2UDWgD4LdQsovnhk8i0i75A==
"@salesforce/source-deploy-retrieve@^9.7.6":
version "9.7.6"
resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-9.7.6.tgz#331d2b6287fa9a5a19fe6e00abe3146002503e1c"
integrity sha512-U6hDvVd/zU4NJJMpaskXVaPOb9RDFjz6fvLWzSjcbVPRbn4QOppi9geAAoDn494Cnspo5pG9/DNoSQ2aKcVK2w==
dependencies:
"@salesforce/core" "^5.2.0"
"@salesforce/core" "^5.2.1"
"@salesforce/kit" "^3.0.9"
"@salesforce/ts-types" "^2.0.5"
"@salesforce/ts-types" "^2.0.7"
fast-levenshtein "^3.0.0"
fast-xml-parser "^4.2.6"
fast-xml-parser "^4.2.7"
got "^11.8.6"
graceful-fs "^4.2.11"
ignore "^5.2.4"
Expand All @@ -704,6 +727,13 @@
dependencies:
tslib "^2.6.1"

"@salesforce/ts-types@^2.0.7":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@salesforce/ts-types/-/ts-types-2.0.7.tgz#02a6999d0b0e7bcd6c6d8ce621c79fa61af24701"
integrity sha512-8csXgstPuy6QXL3JavkIi/f8DOWHBNCvWeszrFu5sbVlcKO3YqOOCE+rDFGPkrZsYv5OywV6H8kEi877bWOz6Q==
dependencies:
tslib "^2.6.2"

"@sindresorhus/is@^4.0.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
Expand Down Expand Up @@ -2491,7 +2521,7 @@ fast-safe-stringify@^2.1.1:
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==

fast-xml-parser@^4.2.5, fast-xml-parser@^4.2.6:
fast-xml-parser@^4.2.5, fast-xml-parser@^4.2.7:
version "4.2.7"
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz#871f2ca299dc4334b29f8da3658c164e68395167"
integrity sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig==
Expand Down Expand Up @@ -5429,6 +5459,11 @@ tslib@^2.0.1, tslib@^2.0.3, tslib@^2.5.3, tslib@^2.6.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410"
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==

tslib@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==

tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
Expand Down

0 comments on commit 1ccea04

Please sign in to comment.