Skip to content
Draft
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
2 changes: 1 addition & 1 deletion packages/http-client-python/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "l0lawrence/typespec-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/tests",
"Tag": "python/tests_7870c7a975"
"Tag": "python/tests_481763e148"
}
59 changes: 57 additions & 2 deletions packages/http-client-python/eng/scripts/ci/render-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { createRequire } from "module";
import { tmpdir } from "os";
import { dirname, join, resolve } from "path";
import pc from "picocolors";
import { fileURLToPath } from "url";
import { fileURLToPath, pathToFileURL } from "url";
import { parseArgs } from "util";

import { FLAVORS, readAssetsConfig, restoreFullBaseline } from "./assets.js";
Expand All @@ -47,6 +47,7 @@ const argv = parseArgs({
output: { type: "string", short: "o" },
generated: { type: "string", short: "g" },
title: { type: "string", short: "t" },
open: { type: "boolean" },
help: { type: "boolean", short: "h" },
},
});
Expand All @@ -61,6 +62,7 @@ ${pc.bold("Options:")}
-o, --output <dir> Output directory (default: temp/diff-site).
-g, --generated <dir> Current generated dir (default: tests/generated).
-t, --title <text> Title shown on the diff page.
--open Open the rendered diff in your default browser.
-h, --help Show this help.
`);
process.exit(0);
Expand Down Expand Up @@ -268,17 +270,41 @@ async function main(): Promise<void> {
writeFileSync(join(OUTPUT_DIR, "summary.json"), JSON.stringify(summary, null, 2) + "\n");
writeSite(diffText, summary);

const indexPath = join(OUTPUT_DIR, "index.html");
console.log(
pc.green(
`Diff rendered to ${OUTPUT_DIR} ` +
`(${summary.filesChanged} files, +${summary.additions}/-${summary.deletions}).`,
),
);
// Print a clickable file:// URL so the page is one click away locally, and
// optionally pop it open in the default browser.
console.log(pc.cyan(`View it at ${pathToFileURL(indexPath).href}`));
if (argv.values.open) {
openInBrowser(indexPath);
}
} finally {
rmSync(workDir, { recursive: true, force: true });
}
}

/** Opens a local file in the OS default browser; never fails the run. */
function openInBrowser(target: string): void {
try {
if (process.platform === "win32") {
// `start` is a cmd builtin; the empty first arg is the window title so a
// path with spaces isn't mistaken for one.
execFileSync("cmd", ["/c", "start", "", target], { stdio: "ignore" });
} else if (process.platform === "darwin") {
execFileSync("open", [target], { stdio: "ignore" });
} else {
execFileSync("xdg-open", [target], { stdio: "ignore" });
}
} catch (err) {
console.warn(pc.yellow(`Could not open a browser automatically: ${err}`));
}
}

interface FileDiff {
/** Display path (baseline/current prefixes stripped). */
path: string;
Expand All @@ -289,6 +315,35 @@ interface FileDiff {
status: "added" | "removed" | "modified";
}

/**
* Rewrites a file chunk's diff header so both sides share the same path.
*
* The diff comes from `git diff --no-index baseline current`, so every header
* reads `a/baseline/<path>` vs `b/current/<path>`. Because those two paths
* differ only by the temp-dir prefix, diff2html mistakes every file for a
* RENAME (showing `{baseline → current}`). Stripping the `baseline/`/`current/`
* prefixes makes old === new path, so it renders as a normal modification.
*/
function normalizeChunkHeader(chunk: string): string {
const lines = chunk.split("\n");
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.startsWith("@@")) break; // header is done once hunks begin
if (line.startsWith("diff --git ")) {
lines[i] = line.replace(/ a\/baseline\//g, " a/").replace(/ b\/current\//g, " b/");
} else if (line.startsWith("--- ")) {
lines[i] = line.replace(/^--- a\/baseline\//, "--- a/");
} else if (line.startsWith("+++ ")) {
lines[i] = line.replace(/^\+\+\+ b\/current\//, "+++ b/");
} else if (line.startsWith("rename from ")) {
lines[i] = line.replace(/^rename from baseline\//, "rename from ");
} else if (line.startsWith("rename to ")) {
lines[i] = line.replace(/^rename to current\//, "rename to ");
}
}
return lines.join("\n");
}

/** Splits a `git diff --no-index` blob into one chunk per file. */
function splitDiffByFile(diffText: string): FileDiff[] {
const files: FileDiff[] = [];
Expand Down Expand Up @@ -323,7 +378,7 @@ function splitDiffByFile(diffText: string): FileDiff[] {
const display = strip(isAdded ? newPath : oldPath) || strip(newPath) || "(unknown)";
files.push({
path: display,
chunk,
chunk: normalizeChunkHeader(chunk),
additions,
deletions,
status: isAdded ? "added" : isRemoved ? "removed" : "modified",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
{{ code_model.license_header }}
{% endif %}

# Generated by the TypeSpec Python emitter.
VERSION = "{{ code_model.options.get("package-version") }}"
2 changes: 2 additions & 0 deletions packages/http-client-python/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
"regenerate": "tsx ./eng/scripts/ci/regenerate.ts",
"regenerate:push-assets": "tsx ./eng/scripts/ci/push-assets.ts",
"regenerate:render-diff": "tsx ./eng/scripts/ci/render-diff.ts",
"regenerate:diff": "tsx ./eng/scripts/ci/render-diff.ts --open",
"regenerate:review": "npm run regenerate && npm run regenerate:diff",
"ci": "npm run test:emitter && npm run ci:generated",
"ci:generated": "tsx ./eng/scripts/ci/run-tests.ts --generator --env=ci",
"change:version": "pnpm chronus version --ignore-policies --only @typespec/http-client-python",
Expand Down
Loading