~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
68 lines · 2.1 KB Raw History
/**
 * Which of a checkout's remotes is the upstream of the copy being pushed.
 *
 * A fork is a clone of somebody else's repository pushed to one's own. The
 * checkout knows both: the remote it was cloned from and the remote it pushes
 * to. When the push goes to a copy under the same name at another account,
 * the remote it came from is the upstream, and the pushed record can say so.
 *
 * Nothing here runs git; the caller hands in what `git config` listed.
 */

import { parseAtprotoUrl } from './url.js';

/**
 * @typedef {Object} Remote
 * @property {string} name
 * @property {string} url
 */

/**
 * The remotes in `git config --get-regexp '^remote\..*\.url$'` output: one
 * line each, `remote.<name>.url <url>`.
 * @param {string} text
 * @returns {Remote[]}
 */
export function parseRemotes(text) {
  /** @type {Remote[]} */
  const remotes = [];
  for (const line of text.split('\n')) {
    const match = /^remote\.(.+)\.url\s+(\S+)\s*$/.exec(line.trim());
    if (match) remotes.push({ name: match[1], url: match[2] });
  }
  return remotes;
}

/**
 * The remote the pushed copy was taken from: an atproto remote naming the
 * same repository at another account, outside any space. Where several fit,
 * `origin` is the one a clone made.
 * @param {Remote[]} remotes
 * @param {{authority: string, repoName: string, space?: unknown}} target -
 *   where the push is going
 * @returns {{name: string, authority: string, repoName: string}|null}
 */
export function upstreamRemote(remotes, target) {
  if (target.space) return null;
  /** @type {Array<{name: string, authority: string, repoName: string}>} */
  const fits = [];
  for (const remote of remotes) {
    /** @type {ReturnType<typeof parseAtprotoUrl>} */
    let parsed;
    try {
      parsed = parseAtprotoUrl(remote.url);
    } catch {
      continue;
    }
    if (parsed.repoName !== target.repoName) continue;
    if (parsed.authority.toLowerCase() === target.authority.toLowerCase()) {
      continue;
    }
    fits.push({
      name: remote.name,
      authority: parsed.authority,
      repoName: parsed.repoName,
    });
  }
  return fits.find((one) => one.name === 'origin') ?? fits[0] ?? null;
}