-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix validation of modified declarations #1066
Changes from 5 commits
2a71f5c
ac0196a
7e3c216
3d0d760
b4177c2
0375139
7357620
ec90771
68b2c86
261582b
9a26d32
24e67a0
cb55fbb
5450277
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "Service", | ||
"documents": { | ||
"Terms of Service": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
}, | ||
"Privacy Policy": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "Service", | ||
"documents": { | ||
"Terms of Service": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body", | ||
"remove": "footer" | ||
}, | ||
"Privacy Policy": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body", | ||
"remove": "footer" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "Service", | ||
"documents": { | ||
"Terms of Service": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
}, | ||
"Privacy Policy": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
}, | ||
"Imprint": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "Service", | ||
"documents": { | ||
"Terms of Service": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "Service", | ||
"documents": { | ||
"Terms of Service": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body", | ||
"remove": "footer" | ||
}, | ||
"Privacy Policy": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "Service B", | ||
"documents": { | ||
"Terms of Service": { | ||
"fetch": "https://domain.example/tos", | ||
"select": "body" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,6 +1,5 @@ | ||||||
import path from 'path'; | ||||||
|
||||||
import DeepDiff from 'deep-diff'; | ||||||
import simpleGit from 'simple-git'; | ||||||
|
||||||
export default class DeclarationUtils { | ||||||
|
@@ -9,13 +8,17 @@ export default class DeclarationUtils { | |||||
this.defaultBranch = defaultBranch; | ||||||
} | ||||||
|
||||||
static filePathToServiceId = filePath => path.parse(filePath.replace(/\.history|\.filters/, '')).name; | ||||||
static getServiceIdFromFilePath(filePath) { | ||||||
return path.parse(filePath.replace(/\.history|\.filters/, '')).name; | ||||||
} | ||||||
|
||||||
async getJSONFile(path, ref) { | ||||||
async getJSONFromFile(ref, filePath) { | ||||||
try { | ||||||
return JSON.parse(await this.git.show([`${ref}:${path}`])); | ||||||
} catch (e) { | ||||||
return {}; | ||||||
const fileContent = await this.git.show([`${ref}:${filePath}`]); | ||||||
|
||||||
return JSON.parse(fileContent); | ||||||
} catch (error) { | ||||||
return undefined; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -24,7 +27,7 @@ export default class DeclarationUtils { | |||||
|
||||||
const modifiedFilePaths = (modifiedFilePathsAsString ? modifiedFilePathsAsString.split('\0') : []).filter(str => str !== ''); // split on \0 rather than \n due to the -z option of git diff | ||||||
|
||||||
return { modifiedFilePaths, modifiedServicesIds: Array.from(new Set(modifiedFilePaths.map(DeclarationUtils.filePathToServiceId))) }; | ||||||
return { modifiedFilePaths, modifiedServicesIds: Array.from(new Set(modifiedFilePaths.map(DeclarationUtils.getServiceIdFromFilePath))) }; | ||||||
} | ||||||
|
||||||
async getModifiedServices() { | ||||||
|
@@ -33,48 +36,55 @@ export default class DeclarationUtils { | |||||
return modifiedServicesIds; | ||||||
} | ||||||
|
||||||
async getModifiedServiceTermsTypes() { | ||||||
const { modifiedFilePaths, modifiedServicesIds } = await this.getModifiedData(); | ||||||
async getModifiedServicesTermsTypes() { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If, as I understand from the tests, this actually returns
Suggested change
(but also, why should it duplicate information that can be obtained with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I not changed the previous API |
||||||
const { modifiedFilePaths } = await this.getModifiedData(); | ||||||
const servicesTermsTypes = {}; | ||||||
|
||||||
await Promise.all(modifiedFilePaths.map(async modifiedFilePath => { | ||||||
const serviceId = DeclarationUtils.filePathToServiceId(modifiedFilePath); | ||||||
const serviceId = DeclarationUtils.getServiceIdFromFilePath(modifiedFilePath); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extract the block in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not understand what you mean here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The whole anonymous function that is defined and called as the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the code simplification, I no longer find it useful. |
||||||
|
||||||
if (modifiedFilePath.endsWith('.filters.js')) { | ||||||
const declaration = await this.getJSONFromFile(this.defaultBranch, `declarations/${serviceId}.json`); | ||||||
|
||||||
if (!modifiedFilePath.endsWith('.json')) { | ||||||
// Here we should compare AST of both files to detect on which function | ||||||
// change has been made, and then find which terms type depends on this | ||||||
// function. | ||||||
// As this is a complicated process, we will just send back all terms types | ||||||
const declaration = await this.getJSONFile(`declarations/${serviceId}.json`, this.defaultBranch); | ||||||
// TODO: Implement AST comparison between original and modified "filters" files to detect changes in functions, enabling identification of terms whose types depend on modified functions. | ||||||
// Due to the complexity involved, temporarily returning all term types. | ||||||
Ndpnt marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
servicesTermsTypes[serviceId] = Object.keys(declaration.documents); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
|
||||||
return Object.keys(declaration.documents); | ||||||
return; | ||||||
} | ||||||
|
||||||
const defaultFile = await this.getJSONFile(modifiedFilePath, this.defaultBranch); | ||||||
const modifiedFile = await this.getJSONFile(modifiedFilePath, 'HEAD'); | ||||||
const originalService = await this.getJSONFromFile(this.defaultBranch, modifiedFilePath); | ||||||
const modifiedService = await this.getJSONFromFile('HEAD', modifiedFilePath); | ||||||
const modifiedServiceTermsTypes = Object.keys(modifiedService.documents); | ||||||
|
||||||
const diff = DeepDiff.diff(defaultFile, modifiedFile); | ||||||
if (!originalService) { | ||||||
servicesTermsTypes[serviceId] = modifiedServiceTermsTypes; | ||||||
|
||||||
if (!diff) { | ||||||
// This can happen if only a lint has been applied to a document | ||||||
return; | ||||||
} | ||||||
|
||||||
const modifiedTermsTypes = diff.reduce((acc, { path }) => { | ||||||
if (modifiedFilePath.includes('.history')) { | ||||||
acc.add(path[0]); | ||||||
} else if (path[0] == 'documents') { | ||||||
acc.add(path[1]); | ||||||
} | ||||||
const originalServiceTermsTypes = Object.keys(originalService.documents); | ||||||
const addedTermsTypes = modifiedServiceTermsTypes.filter(termsType => !originalServiceTermsTypes.includes(termsType)); | ||||||
|
||||||
return acc; | ||||||
}, new Set()); | ||||||
if (addedTermsTypes.length) { | ||||||
servicesTermsTypes[serviceId] = addedTermsTypes; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, why do we assign instead of inserting? Couldn't there be both additions and changes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope it's not possible, you can't both declare a new service and have terms that changed for this service. If it's a new service you can only have all terms added. |
||||||
} | ||||||
|
||||||
const potentiallyModifiedTermsTypes = modifiedServiceTermsTypes.filter(termsType => originalServiceTermsTypes.includes(termsType)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use two filters in a row to partition a space in two, this is inefficient and unclear.
|
||||||
|
||||||
potentiallyModifiedTermsTypes.forEach(termsType => { | ||||||
const areTermsModified = JSON.stringify(originalService.documents[termsType]) != JSON.stringify(modifiedService.documents[termsType]); | ||||||
|
||||||
if (!areTermsModified) { | ||||||
return; | ||||||
} | ||||||
|
||||||
servicesTermsTypes[serviceId] = Array.from(new Set([ ...servicesTermsTypes[serviceId] || [], ...modifiedTermsTypes ])); | ||||||
servicesTermsTypes[serviceId] = [termsType].concat(servicesTermsTypes[serviceId] || []); | ||||||
Ndpnt marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
}); | ||||||
})); | ||||||
|
||||||
return { | ||||||
services: modifiedServicesIds, | ||||||
services: Object.keys(servicesTermsTypes), | ||||||
servicesTermsTypes, | ||||||
}; | ||||||
} | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.