message: Yarn files diffed
diff: @@ -4,8 +4,10 @@ import { join } from 'path';
  import slash from 'slash';
  import { URL } from 'url';
  +import { buildDepTreeFromFiles } from 'snyk-nodejs-lockfile-parser';
  import { getDependentStoryFiles } from '../lib/getDependentStoryFiles';
  import { createTask, transitionTo } from '../lib/tasks';
  +import { checkoutFile } from '../git/git';
  import makeZipFile from '../lib/compress';
  import uploadFiles from '../lib/uploadFiles';
  import { rewriteErrorMessage } from '../lib/utils';
  @@ -142,6 +144,29 @@ export const validateFiles = async (ctx: Context) => {
  }
  };
  +// at each step, put the dependency on the set
  +// (so duplicates are replaced)
  +const flattenDependencyTree = (
  + dependencies: Record<string, any>,
  + flattenedResults = new Set<string>()
  +) => {
  + Object.values(dependencies).forEach((dep) => {
  + flattenedResults.add(`${dep.name}@@${dep.version}`);
  + if (dep.dependencies) {
  + flattenDependencyTree(dep.dependencies, flattenedResults);
  + }
  + });
  + return flattenedResults;
  +};
  +
  +const xor = (left: Set<string>, right: Set<string>) => {
  + Array.from(right.values()).forEach((pkg) => {
  + if (left.has(pkg)) left.delete(pkg);
  + else left.add(pkg);
  + });
  + return left;
  +};
  +
  export const traceChangedFiles = async (ctx: Context, task: Task) => {
  if (!ctx.git.changedFiles) return;
  if (!ctx.fileInfo.statsPath) {
  @@ -156,6 +181,30 @@ export const traceChangedFiles = async (ctx: Context, task: Task) => {
  const { changedFiles } = ctx.git;
  try {
  const stats = await readStatsFile(statsPath);
  +
  + // build the current dep tree
  + const newDepTree = await buildDepTreeFromFiles('.', 'package.json', 'package-lock.json', true);
  + const dependencies = flattenDependencyTree((newDepTree as any).dependencies);
  +
  + return;
  + // diff two sets (looking only for what's added + removed)
  + const res = xor(new Set(['lodash@1.2.3', 'lodash@2.3.4']), new Set(['lodash@1.2.3']));
  +
  + // for both branches (if merge commit), diff with our most-recent thing
  + const baselineChanges = await Promise.all(
  + ctx.git.baselineCommits.map(async (commit) => {
  + const manifestFile = await checkoutFile(commit, 'package.json');
  + const lockfileName = await checkoutFile(commit, 'package-lock.json');
  + const depTree = await buildDepTreeFromFiles('.', manifestFile, lockfileName, true);
  + const depSet = flattenDependencyTree((depTree as any).dependencies);
  + return Array.from(xor(depSet, dependencies));
  + })
  + );
  + // combine all the diffs into one place
  + // we only need unique package names, so we can dedupe after we remove the version from the package name
  + const changedDependencies = new Set(baselineChanges.flat().map((pkg) => pkg.split('@@')[0]));
  +
  + // throw this list of diffs into here!
  const onlyStoryFiles = await getDependentStoryFiles(ctx, stats, statsPath, changedFiles);
  if (onlyStoryFiles) {
  ctx.onlyStoryFiles = Object.keys(onlyStoryFiles);
  