Skip to content

Instantly share code, notes, and snippets.

@K0IN
Last active February 8, 2022 21:57
Show Gist options
  • Save K0IN/1279d73dcecdd8c9388ac7acb0615419 to your computer and use it in GitHub Desktop.
Save K0IN/1279d73dcecdd8c9388ac7acb0615419 to your computer and use it in GitHub Desktop.
A script (Deno) to clone a users repos
// deno run --allow-net --allow-run --allow-write .\clone_all_start_repos.ts --user k0in --mirror
import { parse } from "https://deno.land/std@0.125.0/flags/mod.ts";
const { user, mirror, what = "repos" } = parse(Deno.args); // what can be repos, starred
interface RepoInfo {
id: number;
name: string;
full_name: string;
private: boolean;
owner: {
login: string;
};
clone_url: string;
ssh_url: string;
git_url: string;
}
const fetchAllStartedRepos = async (user: string, what: string): Promise<Array<RepoInfo>> => {
let page = 1;
const repos = [];
while (true) {
const url = `https://api.github.com/users/${user}/${what}?per_page=100&page=${page}`;
const res = await fetch(url);
const json = await res.json();
if (json.length === 0) {
break;
}
repos.push(...json);
page += 1;
}
return repos;
}
const cloneOrUpdateRepo = async (repo: RepoInfo, mirror: boolean) => {
try {
await Deno.remove(repo.name, { recursive: true });
} catch (e) {
console.error(e);
}
const cmd = ["git", "clone", mirror ? "--mirror" : "", repo.clone_url, repo.owner.login + "/" + repo.name].filter(Boolean);
const p = Deno.run({ cmd, stderr: "piped" });
await p.status();
const { code } = await p.status();
if (code !== 0) {
const rawError = await p.stderrOutput();
const errorString = new TextDecoder().decode(rawError);
throw new Error(`failed to clone ${repo.full_name} due to ${errorString}`)
}
}
const startedRepos = await fetchAllStartedRepos(user, what);
const promise = await Promise.allSettled(startedRepos.map(repo => cloneOrUpdateRepo(repo, mirror)));
console.error(promise.filter(e => e.status === "rejected"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment