epicweb-dev / epicshop

The workshop app for all workshops on EpicWeb.dev

Home Page:https://www.epicweb.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Diff viewer doesn't update with changes made between working copy and solution

aaronmcadam opened this issue · comments

The diff viewer doesn't update with my changes.

Expected Behaviour

I expected to see the differences between my test code and the solution's test code.

Actual Behaviour

I see no changes in the diff panel.

Steps to Reproduce

  1. Start the first exercise and write some of the test
  2. Click on the Diff tab
  3. See there are no changes between the problem and the solution code.

Screenshots

CleanShot 2023-10-21 at 23 07 59
Diffing the problem and solution

CleanShot 2023-10-22 at 00 12 34
Trying to view the refactorings made by Kellie 🧝‍♀️

This may be related, but I also see an empty file list when clicking on Files in the bottom panel:
CleanShot 2023-10-23 at 09 25 11

I've seen this before but I've not been able to reproduce it reliably. Is it happening for you 100% of the time?

Yeah to put it another way, I've never seen it work for me on any of the lessons in this testing module.

Oh, so it's just the testing module? Does it work in other modules?

I've not started the other modules yet, I'll try one of them tomorrow and let you know ☺️

I've had the exact same issue that "No Changes" always shows on the Full Stack Foundations module, but I do see my list of files when i click on Files in the bottom panel.

Thank you both for reporting this issue! If you are willing and able to help me debug this I would really appreciate it!

Let me give you some background info. The way this feature works is we're comparing two apps (the playground and the solution for example). We use the git diff --no-index feature to accomplish this. However, we can't just run that on the directories as they are because there are some files I want excluded from the diff (and .gitignore doesn't work with --no-index). So for performance and other reasons, we need to copy select files from the actual location into a temporary location and perform the --no-index diff there.

Here's where the copy logic lives:

https://github.com/epicweb-dev/kcdshop/blob/ab590025aab758a832b98dfd4fc91fab639b4b3a/packages/workshop-app/app/utils/diff.server.ts#L223-L263

With that done, we then run the --no-index diff:

https://github.com/epicweb-dev/kcdshop/blob/ab590025aab758a832b98dfd4fc91fab639b4b3a/packages/workshop-app/app/utils/diff.server.ts#L314-L319

From there, we parse the git diff output:

https://github.com/epicweb-dev/kcdshop/blob/ab590025aab758a832b98dfd4fc91fab639b4b3a/packages/workshop-app/app/utils/diff.server.ts#L331

And then we use that to determine the files to show.

Similar process to getting the actual diff for the diff tab.

So something's messed up in that process. The easiest way to debug this is probably to stick a bunch of console logs all over the place in that code. You'll find it in node_modules/@kentcdodds/workshop-app/build/index.js around line 6909.

You might comment out these lines as well:

https://github.com/epicweb-dev/kcdshop/blob/ab590025aab758a832b98dfd4fc91fab639b4b3a/packages/workshop-app/app/utils/diff.server.ts#L321-L322

That way you can inspect what files were copied over and make certain that they were copied properly. Then you can also manually run git diff --no-index on those directories as well and make sure you're getting the proper diff.

My hunch is that there's a problem with the module we're using the parse the git diff parse-git-diff: https://github.com/yeonjuan/parse-git-diff

I've had a few issues with it in the past, but the maintainer @yeonjuan is awesome and has been very helpful in fixing those issues pretty quickly.

I really appreciate any help you can offer. This has been hard to reproduce, so you're really doing something for me that I can't do for myself. If you're willing and able we can also schedule a time to pair on this as well.

!!! BEFORE READING THIS SKIP TO MY FOLLOWING COMMENT!!!
Hey Kent, sure thing, I'd love to help with figuring this out, will try my best to help.
apologies if this is not much help, I've very limited experience of doing this type of debugging!

I've added a bunch of comments to node_modules/@kentcdodds/workshop-app/build/index.js as you recommended, not sure exactly if the results are useful, I can add more if you think it helps.

This is the commented code from line 6864

async function prepareForDiff(app1, app2) {
  console.log('Preparing for diff for apps:', app1.name, app2.name);

  let workshopRoot2 = getWorkshopRoot();  
  console.log('Workshop root:', workshopRoot2);
 let id = Math.random().toString(36).slice(2); 
 let app1CopyPath = path11.join(
    diffTmpDir,
    path11.basename(workshopRoot2),
    app1.name,
    id
  );
  console.log('app1CopyPath:', app1CopyPath);

  let app2CopyPath = path11.join(
    diffTmpDir,
    path11.basename(workshopRoot2),
    app2.name,
    id
  );
  console.log('app2CopyPath:', app2CopyPath);
  let comparePkgJson = (pkg1, pkg2) => {
    let { name, ...rest1 } = pkg1, { name: name2, ...rest2 } = pkg2;
    return JSON.stringify(rest1) === JSON.stringify(rest2);
  }; 
  let app1PkgJson = app1.dev.type === "script" ? await fsExtra7.readJSON(path11.join(app1.fullPath, "package.json")) : {}; 
  console.log('app1PkgJson:', app1PkgJson);

  let app2PkgJson = app1.dev.type === "script" ? await fsExtra7.readJSON(path11.join(app2.fullPath, "package.json")) : {}; 
  console.log('app2PkgJson:', app2PkgJson);

  let ignore = comparePkgJson(app1PkgJson, app2PkgJson) ? ["package.json"] : [];
  console.log('Ignore list:', ignore);

  await Promise.all([
    copyUnignoredFiles(app1.fullPath, app1CopyPath, ignore),
    copyUnignoredFiles(app2.fullPath, app2CopyPath, ignore)
  ]);

  console.log('Files copied successfully.');

  return { app1CopyPath, app2CopyPath };
}
function getForceFreshForDiff(app1, app2, cacheEntry) {
  if (!cacheEntry)
    return !0;
  let app1Modified = modifiedTimes.get(app1.fullPath) ?? 0, app2Modified = modifiedTimes.get(app2.fullPath) ?? 0, cacheModified = cacheEntry.metadata.createdTime;
  return !cacheModified || app1Modified > cacheModified || app2Modified > cacheModified || void 0;
}
async function getDiffFiles(app1, app2, {
  forceFresh = !1,
  timings,
  request
} = {}) {
  let key = `${app1.relativePath}__vs__${app2.relativePath}`, cacheEntry = await diffFilesCache.get(key);
  return await cachified2({
    key,
    cache: diffFilesCache,
    forceFresh: forceFresh || getForceFreshForDiff(app1, app2, cacheEntry),
    timings,
    request,
    getFreshValue: () => getDiffFilesImpl(app1, app2)
  });
}
function getAppTestFiles(app) {
  console.log(`Getting test files for app: ${app.name}`);

  return app.test.type === "browser" ? app.test.testFiles : [];
}
async function getDiffFilesImpl(app1, app2) {
  console.log(`Getting diff files between app1: ${app1.name} and app2: ${app2.name}`);

  if (app1.name === app2.name)
  console.log("App names are identical, returning an empty array.");

    return [];
}
async function getDiffCode(app1, app2, {
  forceFresh = !1,
  timings,
  request
} = {}) {
  let key = `${app1.relativePath}__vs__${app2.relativePath}`, cacheEntry = await diffCodeCache.get(key);
  return await cachified2({
    key,
    cache: diffCodeCache,
    forceFresh: forceFresh || getForceFreshForDiff(app1, app2, cacheEntry),
    timings,
    request,
    getFreshValue: () => getDiffCodeImpl(app1, app2)
  });
}
async function getDiffCodeImpl(app1, app2) {
  let markdownLines = [""];
  if (app1.name === app2.name)
    return markdownLines.push(
      '<p className="p-4 text-center">You are comparing the same app</p>'
    ), await compileMarkdownString(markdownLines.join(`
`));
  let { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2), { stdout: diffOutput } = await execa2(
    "git",
    [
      "diff",
      "--no-index",
      app1CopyPath,
      app2CopyPath,
      "--color=never",
      "--color-moved-ws=allow-indentation-change",
      "--no-prefix",
      "--ignore-blank-lines"
    ],
    { cwd: diffTmpDir }
    // --no-index implies --exit-code, so we need to ignore the error
  ).catch((e) => {
    console.error("Error during git diff:", e);
    return e;
  });
  console.log(`Diff output: ${diffOutput}`);

  //fsExtra7.remove(app1CopyPath), fsExtra7.remove(app2CopyPath);

  let parsed = parseGitDiff(diffOutput);
  console.log('Raw git diff output:', diffOutput);
  console.log('Parsed git diff:', JSON.stringify(parsed, null, 2));
  console.log(`Parsed git diff: ${JSON.stringify(parsed)}`);

  parsed.files.length || markdownLines.push(
    '<div className="m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background">No changes</div>'
  );
  let app1TestFiles = getAppTestFiles(app1), app2TestFiles = getAppTestFiles(app2);
  console.log('App1 Test Files:', app1TestFiles);
console.log('App2 Test Files:', app2TestFiles);
  for (let file of parsed.files) {
    let pathToCopy = file.type === "RenamedFile" ? file.pathBefore : file.path, relativePath = diffPathToRelative(pathToCopy);
    console.log('Current File:', file);
    console.log('Relative Path:', relativePath);
    if (app1TestFiles.includes(relativePath))
      continue;
    let filePathApp1 = path11.join(app1.fullPath, relativePath), pathToApp2 = file.type === "RenamedFile" ? file.pathAfter : file.path, relativePathApp2 = diffPathToRelative(pathToApp2);
    if (app2TestFiles.includes(relativePathApp2))
      continue;
    let filePathApp2 = path11.join(app2.fullPath, relativePathApp2);
    console.log('File Path App1:', filePathApp1);
    console.log('File Path App2:', filePathApp2);
    switch (file.type) {
      case "ChangedFile": {
        console.log('Processing a ChangedFile:', relativePath);  

        markdownLines.push(`

<Accordion title=${JSON.stringify(relativePath)} variant="changed">

${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join(`
`)}

</Accordion>

`);
        break;
      }
      case "DeletedFile": {
        console.log('Processing a DeletedFile:', relativePath);  

        markdownLines.push(`
<Accordion title=${JSON.stringify(relativePath)} variant="deleted">

${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join(`
`)}

</Accordion>
`);
        break;
      }
      case "RenamedFile": {
        console.log('Processing a RenamedFile from', file.pathBefore, 'to', file.pathAfter);  

        let relativeBefore = diffPathToRelative(file.pathBefore), relativeAfter = diffPathToRelative(file.pathAfter), title = JSON.stringify(`${relativeBefore} \u25B6\uFE0F ${relativeAfter}`);
        markdownLines.push(`
<Accordion title=${title} variant="renamed">

${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join(`
`)}

</Accordion>
`);
        break;
      }
      case "AddedFile": {
        console.log('Processing an AddedFile:', relativePath);  

        markdownLines.push(`
<Accordion title=${JSON.stringify(relativePath)} variant="added">

${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join(`
`)}

</Accordion>
`);
        break;
      }
      default:
        console.error('Unknown file type encountered:', file);  

        throw console.error(file), new Error(`Unknown file type: ${file}`);
    }
  }
  return await compileMarkdownString(markdownLines.join(`
`));
}

and these are the log results

Preparing for diff for apps: playground exercises__sep__02.routing__sep__01.solution.routes
Workshop root: /Users/markmulvaney/Local-Sites/full-stack-foundations
app1CopyPath: /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/playground/cpcixu7usru
app2CopyPath: /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/exercises__sep__02.routing__sep__01.solution.routes/cpcixu7usru
Getting diff files between app1: exercises__sep__02.routing__sep__01.problem.routes and app2: exercises__sep__02.routing__sep__01.solution.routes
app1PkgJson: {
  name: 'exercises__sep__02.routing__sep__01.problem.routes',
  private: true,
  sideEffects: false,
  type: 'module',
  imports: { '#*': './*' },
  scripts: {
    build: 'run-s build:*',
    'build:remix': 'remix build --sourcemap',
    'build:server': 'tsx ./other/build-server.ts',
    dev: 'remix dev --manual -c "node ./server/dev-server.js"',
    test: 'playwright test',
    start: 'remix-serve build',
    lint: 'eslint .',
    typecheck: 'tsc'
  },
  dependencies: {
    '@kentcdodds/workshop-app': '^2.56.2',
    '@mswjs/data': '^0.14.0',
    '@radix-ui/react-label': '^2.0.2',
    '@radix-ui/react-slot': '^1.0.2',
    '@remix-run/css-bundle': '2.1.0',
    '@remix-run/express': '2.1.0',
    '@remix-run/node': '2.1.0',
    '@remix-run/react': '2.1.0',
    '@remix-run/serve': '2.1.0',
    address: '^2.0.1',
    chalk: '^5.3.0',
    'class-variance-authority': '^0.7.0',
    'close-with-grace': '^1.2.0',
    clsx: '^2.0.0',
    compression: '^1.7.4',
    express: '^4.18.2',
    'get-port': '^7.0.0',
    glob: '^10.3.10',
    isbot: '^3.7.0',
    morgan: '^1.10.0',
    react: '^18.2.0',
    'react-dom': '^18.2.0',
    'tailwind-merge': '^1.14.0',
    tailwindcss: '^3.3.3',
    'tailwindcss-animate': '^1.0.7',
    zod: '^3.22.4'
  },
  devDependencies: {
    '@playwright/test': '^1.39.0',
    '@remix-run/dev': '2.1.0',
    '@remix-run/eslint-config': '2.1.0',
    '@total-typescript/ts-reset': '^0.5.1',
    '@types/compression': '^1.7.4',
    '@types/express': '^4.17.20',
    '@types/fs-extra': '^11.0.2',
    '@types/morgan': '^1.9.6',
    '@types/react': '^18.2.28',
    '@types/react-dom': '^18.2.13',
    autoprefixer: '^10.4.16',
    chokidar: '^3.5.3',
    dotenv: '^16.3.1',
    esbuild: '0.19.5',
    eslint: '^8.51.0',
    'eslint-config-prettier': '^9.0.0',
    execa: '^8.0.1',
    'fs-extra': '^11.1.1',
    'npm-run-all': '^4.1.5',
    prettier: '^3.0.3',
    'prettier-plugin-tailwindcss': '^0.5.6',
    'remix-flat-routes': '^0.6.1',
    tsx: '^3.14.0',
    typescript: '^5.2.2'
  },
  engines: { node: '18' },
  eslintIgnore: [
    '/node_modules',
    '/build',
    '/public/build',
    '/playwright-report',
    '/server-build'
  ]
}
app2PkgJson: {
  name: 'exercises__sep__02.routing__sep__01.solution.routes',
  private: true,
  sideEffects: false,
  type: 'module',
  imports: { '#*': './*' },
  scripts: {
    build: 'run-s build:*',
    'build:remix': 'remix build --sourcemap',
    'build:server': 'tsx ./other/build-server.ts',
    dev: 'remix dev --manual -c "node ./server/dev-server.js"',
    test: 'playwright test',
    start: 'remix-serve build',
    lint: 'eslint .',
    typecheck: 'tsc'
  },
  dependencies: {
    '@kentcdodds/workshop-app': '^2.56.3',
    '@mswjs/data': '^0.14.0',
    '@radix-ui/react-label': '^2.0.2',
    '@radix-ui/react-slot': '^1.0.2',
    '@remix-run/css-bundle': '2.1.0',
    '@remix-run/express': '2.1.0',
    '@remix-run/node': '2.1.0',
    '@remix-run/react': '2.1.0',
    '@remix-run/serve': '2.1.0',
    address: '^2.0.1',
    chalk: '^5.3.0',
    'class-variance-authority': '^0.7.0',
    'close-with-grace': '^1.2.0',
    clsx: '^2.0.0',
    compression: '^1.7.4',
    express: '^4.18.2',
    'get-port': '^7.0.0',
    glob: '^10.3.10',
    isbot: '^3.7.0',
    morgan: '^1.10.0',
    react: '^18.2.0',
    'react-dom': '^18.2.0',
    'tailwind-merge': '^1.14.0',
    tailwindcss: '^3.3.3',
    'tailwindcss-animate': '^1.0.7',
    zod: '^3.22.4'
  },
  devDependencies: {
    '@playwright/test': '^1.39.0',
    '@remix-run/dev': '2.1.0',
    '@remix-run/eslint-config': '2.1.0',
    '@total-typescript/ts-reset': '^0.5.1',
    '@types/compression': '^1.7.4',
    '@types/express': '^4.17.20',
    '@types/fs-extra': '^11.0.2',
    '@types/morgan': '^1.9.6',
    '@types/react': '^18.2.28',
    '@types/react-dom': '^18.2.13',
    autoprefixer: '^10.4.16',
    chokidar: '^3.5.3',
    dotenv: '^16.3.1',
    esbuild: '0.19.5',
    eslint: '^8.51.0',
    'eslint-config-prettier': '^9.0.0',
    execa: '^8.0.1',
    'fs-extra': '^11.1.1',
    'npm-run-all': '^4.1.5',
    prettier: '^3.0.3',
    'prettier-plugin-tailwindcss': '^0.5.6',
    'remix-flat-routes': '^0.6.1',
    tsx: '^3.14.0',
    typescript: '^5.2.2'
  },
  eslintIgnore: [
    '/node_modules',
    '/build',
    '/public/build',
    '/playwright-report',
    '/server-build'
  ]
}
Ignore list: []
Files copied successfully.
Error during git diff: Error: Command failed with exit code 129: git diff --no-index /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/playground/cpcixu7usru /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/exercises__sep__02.routing__sep__01.solution.routes/cpcixu7usru --color=never --color-moved-ws=allow-indentation-change --no-prefix --ignore-blank-lines
usage: git diff --no-index <path> <path>
    at makeError (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/execa/lib/error.js:60:11)
    at handlePromise (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/execa/index.js:124:26)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at getDiffCodeImpl (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/@kentcdodds/workshop-app/app/utils/diff.server.ts:399:4)
    at A (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/cachified/src/getFreshValue.ts:17:24)
    at Module.b (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/cachified/src/cachified.ts:85:17)
    at getDiffCode (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/@kentcdodds/workshop-app/app/utils/diff.server.ts:375:3)
    at async Promise.all (index 0)
    at getDiffProp (file:///Users/markmulvaney/Local-Sites/full-stack-foundations/node_modules/@kentcdodds/workshop-app/app/routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.$type/index.tsx:281:18) {
  shortMessage: 'Command failed with exit code 129: git diff --no-index /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/playground/cpcixu7usru /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/exercises__sep__02.routing__sep__01.solution.routes/cpcixu7usru --color=never --color-moved-ws=allow-indentation-change --no-prefix --ignore-blank-lines',
  command: 'git diff --no-index /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/playground/cpcixu7usru /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/exercises__sep__02.routing__sep__01.solution.routes/cpcixu7usru --color=never --color-moved-ws=allow-indentation-change --no-prefix --ignore-blank-lines',
  escapedCommand: 'git diff --no-index "/var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/playground/cpcixu7usru" "/var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/exercises__sep__02.routing__sep__01.solution.routes/cpcixu7usru" "--color=never" "--color-moved-ws=allow-indentation-change" --no-prefix --ignore-blank-lines',
  exitCode: 129,
  signal: undefined,
  signalDescription: undefined,
  stdout: '',
  stderr: 'usage: git diff --no-index <path> <path>',
  cwd: '/var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff',
  failed: true,
  timedOut: false,
  isCanceled: false,
  killed: false
}
Diff output: 
Raw git diff output: 
Parsed git diff: {
  "type": "GitDiff",
  "files": []
}
Parsed git diff: {"type":"GitDiff","files":[]}
Getting test files for app: playground
Getting test files for app: exercises__sep__02.routing__sep__01.solution.routes
App1 Test Files: []
App2 Test Files: []

I could only get the diff to work when i ran it on the directories without the flags
--color=never --color-moved-ws=allow-indentation-change --no-prefix --ignore-blank-lines

Like so
git diff --no-index /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/playground/vwfrl8ytxk /var/folders/t7/cx3hzzjj3j36rfxc404pqh0c0000gn/T/kcdshop/diff/full-stack-foundations/exercises__sep__02.routing__sep__01.solution.routes/vwfrl8ytxk
and it seems to work, got back the following:

Screenshot 2023-10-30 at 10 31 23

Hey again!

I think you can ignore what I previously wrote.
I fixed the issue on my own side.
It was due to the flag --color-moved-ws=allow-indentation-change not being supported by my ancient version of GIt which was v2.15. I believe this flag requires. v2.18.

I believe in the setup guide it suggests git v2.13 or greater is required, so it could be good to change that to v2.18?
Hopefully this is the issue.
It seems to be working on my end anyways!

Screenshot 2023-10-30 at 11 52 07

Oh! Thank you so much for the help! I will update the requirements and update the setup script to check for the proper version.

I really appreciate you taking the time to work through this :)

Glad to help Kent!

thanks for creating an awesome learning experience 🙌

I've updated the workshops with the git version requirement. Thanks again!

@aaronmcadam, if this fix doesn't work for you please let me know!

hmm still not working for me, my git version is 2.42.0:
CleanShot 2023-10-30 at 18 21 34@2x

I just tried the first workshop (full-stack-foundations) and still I see no changes.

@kentcdodds I'm still seeing no changes 😢

Dang. I'm afraid I don't know what it could be then. If you have time to do a little debugging with some console.logs as mentioned above that would be greatly appreciated.

Hello there! I've been working through the exercises in the Data Modeling workshop and I believe I'm encountering the same issue. The first two workshops were tracking the diff changes properly, but in the Data Modeling workshop I noticed my changes in the prisma/ folder weren't being diffed properly. I also noticed that I can see the changes when I diff the playground with the problem version of the exercise, but when I diff the playground with the solution version it just seems to compare the initial state with the solution files

I'll add some screenshots in this thread to add more context to the issue.

Here's the diff between playground and problem versions. Notice how it properly tracks me commenting out the bit with the firstNote, and leaving the emoji comments intact:
changes being tracked with diffing playground and problem

And here's the diff between playground and solution versions. Notice how the diff shows that the whole bit with the firstNote gets deleted altogether with the emoji comments, leading me to believe it just compares the initial version with the solution in this particular view:
changes not tracked when diffing playground with solution

EDIT: Interestingly, I seem to get the correct diff when I restart the workshop app:
changes now tracked properly after restarting the workshop app

I hope this helps!

I am also experiencing this issue on the Web Auth workshop. The diff works if you restart the workshop app (though usually have to refresh or change app sourcees to see new changes). Once you move to a new exercise and hit "Set to playground" it stops tracking changes.

If there is anything specific you'd like me to test out i'd be happy to.

I ran out of time today to dig into this further but I believe i've isolated the problem down to a cache hit in getDiffFiles.

There may be more than one problem at play here because i'm experiencing a range of quirky behaviors.

  1. Changes in the diff appear upon restarting
  2. Changes usually but not always stop working after changing exercises and updating playground
    2.1. e.g. After changing exercises, the diff on Playground vs app2 wont show correctly but switching app 2 to something else will show the changes made. Subsequent changes made to files will not show.

Hopefully i can find some time next week to step through and document this all with corresponding console log outputs

@kentcdodds
TL:DR;

A cache hit is causing files not to be copied and diffs not to be performed.
I think it is likely related to how the modified times are (& not) being calculated and stored.

The below steps through the process with a lot of console.log output.

I'd be happy to pair on this if we can find a time that works.

Initial page load. Web Auth Module 10. Exercise 01. Resend

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__02.problem.mocks',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.solution.resend
CODE: GET FRESH DIFF
FILES: GETTING FRESH DIFF

CODE: ARE PACKAGE.JSON SAME? true
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/13oew0ar8ta__package.json
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.solution.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/13oew0ar8ta__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/13oew0ar8ta__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.solution.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/13oew0ar8ta__package.json

FILES: ARE PACKAGE.JSON SAME? true
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.problem.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/sbhushwzhr__package.json
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.solution.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/sbhushwzhr__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.problem.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/sbhushwzhr__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.solution.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/sbhushwzhr__package.json

CODE: NOT REMOVING FILES ---------------------------------
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/13oew0ar8ta
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/13oew0ar8ta

CODE PARSED DIFF:
{
  type: 'GitDiff',
  files: [
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/13oew0ar8ta/app/routes/_auth+/signup.tsx'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/13oew0ar8ta/index.js'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/13oew0ar8ta/server/dev-server.js'
    },
    {
      type: 'DeletedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/13oew0ar8ta/tests/mocks/index.ts'
    },
    {
      type: 'DeletedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/13oew0ar8ta/tests/mocks/resend.ts'
    }
  ]
}

FILES: NOT REMOVING --------------------------------------
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/sbhushwzhr
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/sbhushwzhr

FILES PARSED DIFF
{
  type: 'GitDiff',
  files: [
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'b/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/sbhushwzhr/.env'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'b/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/sbhushwzhr/app/utils/email.server.ts'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'b/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.solution.resend/sbhushwzhr/app/utils/env.server.ts'
    }
  ]
}

Clicking Set to Playground

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.solution.resend
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703443178715
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703443018370
FILES: FORCE FRESH?  undefined

Clicking DIFF Tab (Defaults to App1: Playground App2: Solution)

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.solution.resend
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703443178715
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703443018370
FILES: FORCE FRESH?  undefined
Pasted image 20231224124248

Making Change to File

Made a change to .env file then clicked the diff tab to reload the page. No change was detected this time.

This same exact loader log happens with hard refresh as well

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.solution.resend
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703443178715
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703443018370
FILES: FORCE FRESH?  undefined
Failed to fetch progress from EpicWeb: 500
Pasted image 20231224124817

Switching App 2 to Problem

This time the change is detected.

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.problem.resend
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703443018370
FILES: FORCE FRESH?  undefined
CODE: GET FRESH DIFF

CODE: ARE PACKAGE.JSON SAME? true
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/wri2wxrsrya__package.json
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.problem.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/wri2wxrsrya__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/wri2wxrsrya__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/01.problem.resend__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/wri2wxrsrya__package.json

CODE: NOT REMOVING FILES ---------------------------------
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/wri2wxrsrya
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/wri2wxrsrya

CODE PARSED DIFF:
{
  type: 'GitDiff',
  files: [
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__01.problem.resend/wri2wxrsrya/.env'
    }
  ]
}
Pasted image 20231224125401

Making another change

The change is not detected again.

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.problem.resend
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703443977227
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703443018370
FILES: FORCE FRESH?  undefined
Pasted image 20231224125628

Moving ahead to the Solution page of the exercise

Comparing Playground to Solution still shows no user made changes.
Comparing Playground to Problem still only shows the first change I made.

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__01.problem.resend',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/01.problem.resend'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__01.solution.resend',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/01.solution.resend'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/01.problem.resend
	 exercises/10.email/01.solution.resend
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/01.solution.resend
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703443178715
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703443018370
FILES: FORCE FRESH?  undefined

Moving to Next Exercise & Setting Playground

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/02.problem.mocks
	 exercises/10.email/02.solution.mocks
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/02.solution.mocks
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703444254705
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703444254705
FILES: FORCE FRESH?  undefined

--------- SET TO PLAYGROUND --------
---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__01.problem.resend',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/02.problem.mocks
	 exercises/10.email/02.solution.mocks
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/02.solution.mocks
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703443176608 | App2:  0 | Cache:  1703444254705
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703444254705
FILES: FORCE FRESH?  undefined
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/02.solution.mocks
CODE: GET FRESH DIFF

CODE: ARE PACKAGE.JSON SAME? true
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/zbndq1smw5i__package.json
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/02.solution.mocks__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/zbndq1smw5i__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/02.solution.mocks__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i__package.json

CODE: NOT REMOVING FILES ---------------------------------
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/zbndq1smw5i
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i

CODE PARSED DIFF:
{
  type: 'GitDiff',
  files: [
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i/app/routes/_auth+/signup.tsx'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i/index.js'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i/server/dev-server.js'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i/tests/mocks/index.ts'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/zbndq1smw5i/tests/mocks/resend.ts'
    }
  ]
}
Failed to fetch progress from EpicWeb: 500

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__02.problem.mocks',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/02.problem.mocks
	 exercises/10.email/02.solution.mocks
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/02.solution.mocks
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703444614219 | App2:  0 | Cache:  1703444616517
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703444254705
FILES: FORCE FRESH?  undefined
Pasted image 20231224130509

Making Change to index.js

Again no changes are recognized.

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__02.problem.mocks',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/02.problem.mocks
	 exercises/10.email/02.solution.mocks
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/02.solution.mocks
CODE: CHECK DIFF CACHE - Modified Times
 App1:  1703444614219 | App2:  0 | Cache:  1703444616517
CODE: FORCE FRESH?  undefined
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703444254705
FILES: FORCE FRESH?  undefined
Pasted image 20231224130803

Change is seen after switching APP 2 to problem, but no subsequent changes will be detected.

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__02.problem.mocks',
  type: 'playground',
  relativePath: 'playground'
}

APP 2:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/02.problem.mocks
	 exercises/10.email/02.solution.mocks
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 playground
	 exercises/10.email/02.problem.mocks
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703444254705
FILES: FORCE FRESH?  undefined
CODE: GET FRESH DIFF

CODE: ARE PACKAGE.JSON SAME? true
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/g0c34zvok69__package.json
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/02.problem.mocks__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.problem.mocks/g0c34zvok69__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/g0c34zvok69__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/02.problem.mocks__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.problem.mocks/g0c34zvok69__package.json

CODE: NOT REMOVING FILES ---------------------------------
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/g0c34zvok69
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.problem.mocks/g0c34zvok69

CODE PARSED DIFF:
{
  type: 'GitDiff',
  files: [
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.problem.mocks/g0c34zvok69/index.js'
    }
  ]
}
Pasted image 20231224130934

Swapping App1 to solution and App2 to playground

This results in the change that was previously undetected in the diff between playground and solution to be seen.

This is pretty clear proof that cache is the problem.

---------------LOADER-----------------

GetDiffProp:
APP 1:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

APP 2:
 {
  name: 'playground',
  appName: 'exercises__sep__10.email__sep__02.problem.mocks',
  type: 'playground',
  relativePath: 'playground'
}

Problem APP:
 {
  name: 'exercises__sep__10.email__sep__02.problem.mocks',
  appName: undefined,
  type: 'problem',
  relativePath: 'exercises/10.email/02.problem.mocks'
}

Solution APP:
 {
  name: 'exercises__sep__10.email__sep__02.solution.mocks',
  appName: undefined,
  type: 'solution',
  relativePath: 'exercises/10.email/02.solution.mocks'
}

GET DIFF FILES
	app1 vs app2 (relativePath)
	 exercises/10.email/02.problem.mocks
	 exercises/10.email/02.solution.mocks
GET DIFF CODE
	app1 vs app2 ( relativePath)
	 exercises/10.email/02.solution.mocks
	 playground
FILES: CHECK DIFF CACHE - Modified Times
 App1:  0 | App2:  0 | Cache:  1703444254705
FILES: FORCE FRESH?  undefined
CODE: GET FRESH DIFF

CODE: ARE PACKAGE.JSON SAME? true
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/02.solution.mocks__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/2d7umuneoxu__package.json
FILES: COPYING KEY:
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/exercises/10.email/02.solution.mocks__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/2d7umuneoxu__package.json

FILES: COPY UNIGNORED - CACHE MISS
	 COPY_/Users/mezzomind/dev/edu/web-auth/playground__/var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu__package.json

CODE: NOT REMOVING FILES ---------------------------------
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/exercises__sep__10.email__sep__02.solution.mocks/2d7umuneoxu
	 /var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu

CODE PARSED DIFF:
{
  type: 'GitDiff',
  files: [
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu/app/routes/_auth+/signup.tsx'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu/index.js'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu/server/dev-server.js'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu/tests/mocks/index.ts'
    },
    {
      type: 'ChangedFile',
      chunks: [Array],
      path: 'var/folders/n4/gm2tyf1j0n12byb3v9d4k2y00000gn/T/kcdshop/diff/web-auth/playground/2d7umuneoxu/tests/mocks/resend.ts'
    }
  ]
}

Switching it back to App1: Playground, App2: Solution hits the cache again and the change that we just saw disappears.

Ah, caching definitely sounds like the problem. We definitely need to have the cache in place, otherwise generating the diff will just take too long. We just need to work out how to invalidate the cache correctly. The invalidation process is a little tricky though, so we'll need to dive into what's causing that problem further.