Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 45 additions & 26 deletions cli/src/builders/make/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@ interface Step {
* parents: this property controls the all target. It will include all the parents of partial build objects.
* partial: if this property is true, the makefile will only include targets for the partial build objects (and optionally their parents)
*/
type PartialOptions = { partial: boolean, parents: boolean };
type PartialOptions = {
parents?: boolean,
withChildren?: boolean,
parentsChildren?: boolean
};

interface PartialTargets {
partial: ILEObject[];
children?: ILEObject[];
targets: ILEObject[];
children: ILEObject[];
}

export class MakeProject {
private partialOptions: PartialOptions = { partial: false, parents: false };
private partialOptions: PartialOptions|undefined
private settings: iProject = new iProject();
private projectActions: ProjectActions;
private actionsEnabled: boolean = false;
Expand Down Expand Up @@ -235,32 +239,37 @@ export class MakeProject {
return;
}

let allParents: ILEObject[]|undefined;
let children: ILEObject[] = [];

// we also want to build their parents too. We update `partialBuild`
// to include all the parents of the specific objects.
if (this.partialOptions.parents) {
allParents = [];
const impacts = partialBuild.map(o => this.targets.getImpactFor(o));

const addImpact = (impactedObj: ImpactedObject) => {
if (!allParents.some(o => o.systemName === impactedObj.ileObject.systemName && o.type === impactedObj.ileObject.type)) {
allParents.push(impactedObj.ileObject);
}

const allParents: ILEObject[] = [];
const impacts = partialBuild.map(o => this.targets.getImpactFor(o));

impactedObj.children.forEach(child => addImpact(child));
const addImpact = (impactedObj: ImpactedObject) => {
if (!allParents.some(o => o.systemName === impactedObj.ileObject.systemName && o.type === impactedObj.ileObject.type)) {
allParents.push(impactedObj.ileObject);
}

impacts.forEach(impact => addImpact(impact));
impactedObj.children.forEach(child => addImpact(child));
}

partialBuild = allParents;
impacts.forEach(impact => addImpact(impact));

if (this.partialOptions.parentsChildren) {
children = this.targets.getRequiredChildren(allParents);
} else if (this.partialOptions.withChildren) {
children = this.targets.getRequiredChildren(partialBuild);
}

let allChildren: ILEObject[]|undefined = this.partialOptions.partial ? this.targets.getRequiredObjects(partialBuild) : undefined;
if (this.partialOptions.parents) {
partialBuild = allParents;
}

return {
partial: partialBuild,
children: allChildren
targets: partialBuild,
children: children
}
}

Expand All @@ -271,7 +280,7 @@ export class MakeProject {
const buildObjects = this.getPartialTargets(partialBuild);

if (buildObjects) {
partialBuild = buildObjects.partial;
partialBuild = buildObjects.targets;
}

// If we are in partial mode, we only want to generate targets for the specific objects
Expand All @@ -288,9 +297,19 @@ export class MakeProject {
)
}

if (buildObjects && buildObjects.children) {
let allTargetObjects: ILEObject[]|undefined = undefined;
if (this.partialOptions && buildObjects) {
allTargetObjects = [];
if (this.partialOptions.parentsChildren) {
allTargetObjects = partialBuild.concat(buildObjects.children || []).filter((t, i, self) => self.indexOf(t) === i);
} else if (this.partialOptions.withChildren) {
allTargetObjects = buildObjects.children.filter((t, i, self) => self.indexOf(t) === i);
}
}

if (allTargetObjects) {
// If we don't want the children to get built, we only generate the targets for the specific objects
for (const obj of buildObjects.children) {
for (const obj of allTargetObjects) {
if (obj.reference) continue; // Skip references

const target = this.targets.getTarget(obj);
Expand Down Expand Up @@ -324,13 +343,13 @@ export class MakeProject {
return lines;
}

public generateGenericRules(partialBuild?: ILEObject[]): string[] {
public generateGenericRules(buildFor?: ILEObject[]): string[] {
let lines = [];

const buildObjects = this.getPartialTargets(partialBuild);
const buildObjects = this.getPartialTargets(buildFor);

if (buildObjects) {
partialBuild = buildObjects.partial;
buildFor = buildObjects.children.concat(buildObjects.targets);
}

for (const entry of Object.entries(this.settings.compiles)) {
Expand Down Expand Up @@ -376,7 +395,7 @@ export class MakeProject {
for (const ileObject of objects) {
if (ileObject.reference) continue;

if (buildObjects && buildObjects.children && !buildObjects.children.some(o => o.systemName === ileObject.systemName && o.type === ileObject.type)) {
if (buildFor && !buildFor.some(o => o.systemName === ileObject.systemName && o.type === ileObject.type)) {
continue; // Skip this object
}

Expand Down
3 changes: 2 additions & 1 deletion cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ export let cliSettings = {
autoRename: false,
lookupFiles: undefined as string[]|undefined,
userBranch: ``,
makefileIsPartial: false,
makefileWithChildren: true,
makefileWithParents: false,
makefileWithParentsChildren: false,
assumeSourcesArePrograms: false,
};

Expand Down
37 changes: 22 additions & 15 deletions cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@ async function main() {

case '-nc':
case '--no-children':
warningOut(`--no-children is deprecated and is default when doing partial builds.`);
break;

case `-ip`:
case `--is-partial`:
cliSettings.makefileIsPartial = true;
cliSettings.makefileWithChildren = false;
break;

case `-wp`:
case `--with-parents`:
cliSettings.makefileWithParents = true;
break;

case `-wpc`:
case `--with-parents-children`:
cliSettings.makefileWithParentsChildren = true;
break;

case '-ap':
case '--assume-programs':
cliSettings.assumeSourcesArePrograms = true;
Expand Down Expand Up @@ -137,12 +137,16 @@ async function main() {
console.log(``);
console.log(`Options specific to '-bf make':`);
console.log(``);
console.log(`\t-ip`);
console.log(`\t--is-partial\tWill only generate targets that are needed for`);
console.log(`\t\t\tthe objects that are being built.`);
console.log(``);
console.log(`\t-wp`);
console.log(`\t--with-parents\tUsed with '-bf make' and will add parents of`);
console.log(`\t--with-parents\tWill add parents of`);
console.log(`\t\t\tobjects being partially built to the makefile.`);
console.log(``);
console.log(`\t-wpc`);
console.log(`\t--with-parents-children\tWill add children of parents`);
console.log(`\t\t\t\tto makefile.`);
console.log(``);
console.log(`\t-nc`);
console.log(`\t--no-children\tWill not add children of`);
console.log(`\t\t\tobjects being partially built to the makefile.`);
console.log(``);
process.exit(0);
Expand Down Expand Up @@ -246,10 +250,13 @@ async function main() {

await makeProj.setupSettings();

makeProj.setPartialOptions({
partial: cliSettings.makefileIsPartial,
parents: cliSettings.makefileWithParents
})
if (cliSettings.lookupFiles) {
makeProj.setPartialOptions({
withChildren: cliSettings.makefileWithChildren,
parents: cliSettings.makefileWithParents,
parentsChildren: cliSettings.makefileWithParentsChildren
});
}

let specificObjects: ILEObject[] | undefined = cliSettings.lookupFiles ? cliSettings.lookupFiles.map(f => targets.getResolvedObject(path.join(cwd, f))).filter(o => o) : undefined;
writeFileSync(path.join(cwd, `makefile`), makeProj.getMakefile(specificObjects).join(`\n`));
Expand Down
2 changes: 1 addition & 1 deletion cli/src/targets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ export class Targets {
/**
* Returns a list of all the required objects to build this target
*/
public getRequiredObjects(bases: (ILEObject|ILEObjectTarget)[]) {
public getRequiredChildren(bases: (ILEObject|ILEObjectTarget)[]) {
let deps: ILEObject[] = [];

const addDep = (dep: ILEObject|ILEObjectTarget) => {
Expand Down
1 change: 0 additions & 1 deletion cli/src/targets/languages/rpgle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,6 @@ function setupParser(targets: Targets): Parser {
}
} else if (!includeFile.includes(`/`)) {
const parent = path.basename(path.dirname(baseFile));
console.log(parent);
includeFile = `${parent}/${includeFile}`;


Expand Down
4 changes: 2 additions & 2 deletions cli/test/cs_srvpgm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe(`pseudo tests`, () => {
expect(empdet.deps.find(f => f.systemName === `EMPLOYEE`)).toBeDefined();
expect(empdet.deps.find(f => f.systemName === `DEPARTMENT`)).toBeDefined();

const allRequirements = targets.getRequiredObjects([empdet]);
const allRequirements = targets.getRequiredChildren([empdet]);
expect(allRequirements.length).toBe(3);
expect(allRequirements.find(f => f.systemName === `EMPLOYEE` && f.type === `FILE`)).toBeDefined();
expect(allRequirements.find(f => f.systemName === `DEPARTMENT` && f.type === `FILE`)).toBeDefined();
Expand All @@ -69,7 +69,7 @@ describe(`pseudo tests`, () => {
expect(employees.deps.find(f => f.systemName === `EMPS` && f.type === `FILE`)).toBeDefined();
expect(employees.deps.find(f => f.systemName === `EMPLOYEE` && f.type === `FILE`)).toBeDefined();

const requiredForEmployees = targets.getRequiredObjects([employees]);
const requiredForEmployees = targets.getRequiredChildren([employees]);
expect(requiredForEmployees.length).toBe(6);

expect(requiredForEmployees.find(f => f.systemName === `EMPLOYEES` && f.type === `PGM`)).toBeDefined();
Expand Down
109 changes: 108 additions & 1 deletion cli/test/cs_with_bnddir.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe(`pseudo tests`, () => {
expect(employees.deps.find(f => f.systemName === `EMPLOYEE` && f.type === `FILE`)).toBeDefined();
});

test('makefile', async () => {
test('makefile', async () => {
const makefile = new MakeProject(targets.getCwd(), targets, fs);
await makefile.setupSettings();

Expand All @@ -96,6 +96,113 @@ describe(`pseudo tests`, () => {
expect(steps.length).toBe(8);
});

test('makefile partial (without parents, object has no children)', async () => {
const makefile = new MakeProject(targets.getCwd(), targets, fs);
makefile.setPartialOptions({parents: false});
await makefile.setupSettings();

const resolvedObjects = targets.getResolvedObjects();

const nept = resolvedObjects.find(f => f.systemName === `NEMP` && f.type === `FILE`);
const targetsOut = makefile.generateTargets([nept]).join(`\n`);
console.log(targetsOut);

expect(targetsOut).toContain(`all: .logs .evfevent library $(PREPATH)/NEMP.FILE`);
expect(targetsOut).not.toContain(`$(PREPATH)/NEWEMP.PGM:`);

const rules = makefile.generateGenericRules([nept]).join(`\n`);
console.log(rules);

expect(rules).toContain(`$(PREPATH)/NEMP.FILE:`);
});

test('makefile partial (without parents, object with children)', async () => {
const makefile = new MakeProject(targets.getCwd(), targets, fs);
makefile.setPartialOptions({parents: false, withChildren: true});
await makefile.setupSettings();

const resolvedObjects = targets.getResolvedObjects();

const nept = resolvedObjects.find(f => f.systemName === `NEWEMP` && f.type === `PGM`);
const targetsOut = makefile.generateTargets([nept]).join(`\n`);
console.log(targetsOut);

expect(targetsOut).toContain(`all: .logs .evfevent library $(PREPATH)/NEWEMP.PGM`);
expect(targetsOut).toContain(`$(PREPATH)/NEWEMP.PGM:`);

const rules = makefile.generateGenericRules([nept]).join(`\n`);
console.log(rules);

expect(rules).toContain(`$(PREPATH)/NEMP.FILE:`);
});

test('makefile partial (without parents, object with children, but using withChildren false)', async () => {
const makefile = new MakeProject(targets.getCwd(), targets, fs);
makefile.setPartialOptions({parents: false, withChildren: false});
await makefile.setupSettings();

const resolvedObjects = targets.getResolvedObjects();

const nept = resolvedObjects.find(f => f.systemName === `NEWEMP` && f.type === `PGM`);
const targetsOut = makefile.generateTargets([nept]).join(`\n`);
console.log(targetsOut);

expect(targetsOut).toContain(`all: .logs .evfevent library $(PREPATH)/NEWEMP.PGM`);
expect(targetsOut).not.toContain(`$(PREPATH)/NEWEMP.PGM:`);

const rules = makefile.generateGenericRules([nept]).join(`\n`);
console.log(rules);

expect(rules).not.toContain(`$(PREPATH)/NEMP.FILE:`);
expect(rules).toContain(`$(PREPATH)/NEWEMP.PGM: qrpglesrc/newemp.pgm.sqlrpgle`);
});

test('makefile partial (with parents)', async () => {
const makefile = new MakeProject(targets.getCwd(), targets, fs);
makefile.setPartialOptions({parents: true});
await makefile.setupSettings();

const resolvedObjects = targets.getResolvedObjects();

const nept = resolvedObjects.find(f => f.systemName === `NEMP` && f.type === `FILE`);
const targetsOut = makefile.generateTargets([nept]).join(`\n`);
console.log(targetsOut);

expect(targetsOut).toContain(`all: .logs .evfevent library $(PREPATH)/NEMP.FILE $(PREPATH)/NEWEMP.PGM $(PREPATH)/DEPTS.PGM`);
expect(targetsOut).not.toContain(`$(PREPATH)/NEWEMP.PGM:`);

const rules = makefile.generateGenericRules([nept]).join(`\n`);
console.log(rules);

expect(rules).toContain(`$(PREPATH)/NEMP.FILE:`);
expect(rules).toContain(`$(PREPATH)/NEWEMP.PGM:`);
expect(rules).toContain(`$(PREPATH)/DEPTS.PGM:`);
expect(rules).not.toContain(`$(PREPATH)/EMPLOYEES.PGM:`);
});

test('makefile partial (with parents, and children parent)', async () => {
const makefile = new MakeProject(targets.getCwd(), targets, fs);
makefile.setPartialOptions({parents: true, parentsChildren: true});
await makefile.setupSettings();

const resolvedObjects = targets.getResolvedObjects();

const nept = resolvedObjects.find(f => f.systemName === `NEMP` && f.type === `FILE`);
const targetsOut = makefile.generateTargets([nept]).join(`\n`);
console.log(targetsOut);

expect(targetsOut).toContain(`all: .logs .evfevent library $(PREPATH)/NEMP.FILE $(PREPATH)/NEWEMP.PGM $(PREPATH)/DEPTS.PGM`);
expect(targetsOut).toContain(`$(PREPATH)/NEWEMP.PGM: $(PREPATH)/EMPLOYEE.FILE $(PREPATH)/NEMP.FILE`);

const rules = makefile.generateGenericRules([nept]).join(`\n`);
console.log(rules);

expect(rules).toContain(`$(PREPATH)/NEMP.FILE:`);
expect(rules).toContain(`$(PREPATH)/NEWEMP.PGM:`);
expect(rules).toContain(`$(PREPATH)/DEPTS.PGM:`);
expect(rules).toContain(`$(PREPATH)/EMPLOYEES.PGM:`);
});

test('ibmi-bob rules', () => {
const bobProject = new BobProject(targets);

Expand Down
4 changes: 2 additions & 2 deletions cli/test/make.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,15 @@ test('generateTargets (post-resolve)', async () => {
const project = new MakeProject(cwd, targets, new ReadFileSystem());

const srvpgma = targets.getTarget({systemName: `SRVPGMA`, type: `SRVPGM`});
const srvpgmaRequirements = targets.getRequiredObjects([srvpgma]);
const srvpgmaRequirements = targets.getRequiredChildren([srvpgma]);
expect(srvpgmaRequirements.length).toBe(3);
expect(srvpgmaRequirements.map(r => r.systemName)).toEqual([
`FILEB`,
`MODULEB`,
`SRVPGMA`
]);

project.setPartialOptions({partial: true, parents: false});
project.setPartialOptions({withChildren: true});

const targetContent = project.generateTargets([srvpgma]);

Expand Down
Loading
Loading