OXYGENHUB
# f532c4266f21 oxygen-vscode / src / handoff.ts
1.6 KiB · last changed Resolve in VS Code: open a conflict from OxygenHub 1 month ago source blame history raw
1
// "Resolve in VS Code" (OxygenHub's conflict resolver hands a conflict to
2
// the extension): vscode://oxygen.oxygen-vscode/resolve?url=…&bookmark=…&path=…
3
// Parsing and matching live here, apart from VS Code, so they are tested.
4
5
export interface ResolveRequest {
6
  /** The repository's clone URL on the hub. */
7
  url: string;
8
  bookmark: string;
9
  /** Relative to the repository root. */
10
  path: string;
11
}
12
13
/** Read a resolve request's query string, or say what is wrong with it. */
14
export function parseResolveQuery(query: string): ResolveRequest | string {
15
  const q = new URLSearchParams(query);
16
  const url = (q.get("url") ?? "").trim();
17
  const bookmark = (q.get("bookmark") ?? "").trim();
18
  const path = (q.get("path") ?? "").trim().replace(/^\/+/, "");
19
  if (!/^https?:\/\/[^\s]+$/.test(url)) {
20
    return "the link names no repository URL";
21
  }
22
  if (!bookmark || /[\s~^:?*[\\]/.test(bookmark) || bookmark.includes("..")) {
23
    return "the link names no valid bookmark";
24
  }
25
  if (!path || path.split("/").some((c) => c === "" || c === "." || c === ".." || c === ".oxy")) {
26
    return "the link names no valid path";
27
  }
28
  return { url, bookmark, path };
29
}
30
31
/** Whether two remote URLs name the same repository (case of the host and a trailing slash aside). */
32
export function sameRemote(a: string, b: string): boolean {
33
  const norm = (u: string) => {
34
    try {
35
      const x = new URL(u.trim());
36
      return `${x.protocol}//${x.host.toLowerCase()}${x.pathname.replace(/\/+$/, "").replace(/\.oxy$/, "")}`;
37
    } catch {
38
      return u.trim().replace(/\/+$/, "");
39
    }
40
  };
41
  return norm(a) === norm(b);
42
}