mirror of
https://github.com/HeyPuter/puter
synced 2024-11-14 22:06:00 +00:00
feat(git): Implement git fetch
Sporadically we hang while trying to fetch. I haven't been able to identify why but it seems like a race condition in isomorphic-git somewhere.
This commit is contained in:
parent
c86e4dfdce
commit
98a4b9ede3
@ -17,6 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import path from 'path-browserify';
|
||||
import git from 'isomorphic-git';
|
||||
|
||||
export const PROXY_URL = 'https://cors.isomorphic-git.org';
|
||||
|
||||
@ -84,3 +85,28 @@ export const shorten_hash = (hash) => {
|
||||
// TODO: Ensure that whatever we produce is unique within the repo
|
||||
return hash.slice(0, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the remot/url parameters to pass to git.fetch(), based on a `<repository>` string.
|
||||
* @param remote_name_or_url Command-line parameter, either a remote name, an url, or undefined.
|
||||
* @param remotes List of all existing remotes, from `git.listRemotes()`
|
||||
* @returns {remote, url} Object with fields to pass to git.fetch() or similar.
|
||||
*/
|
||||
export const determine_fetch_remote = (remote_name_or_url, remotes) => {
|
||||
if (!remote_name_or_url) {
|
||||
// We leave `url` and `remote` blank and git.fetch() handles the default.
|
||||
return {};
|
||||
}
|
||||
|
||||
if (URL.canParse(remote_name_or_url)) {
|
||||
return { url: remote_name_or_url };
|
||||
}
|
||||
|
||||
// Named remote. First, check if the remote exists. `git.fetch` reports non-existent remotes as:
|
||||
// "The function requires a "remote OR url" parameter but none was provided."
|
||||
// ...which is not helpful to the user.
|
||||
const remote_data = remotes.find(it => it.remote === remote_name_or_url);
|
||||
if (!remote_data)
|
||||
throw new Error(`'${remote_name_or_url}' does not appear to be a git repository`);
|
||||
return remote_data;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import module_branch from './branch.js'
|
||||
import module_clone from './clone.js'
|
||||
import module_commit from './commit.js'
|
||||
import module_config from './config.js'
|
||||
import module_fetch from './fetch.js'
|
||||
import module_help from './help.js'
|
||||
import module_init from './init.js'
|
||||
import module_log from './log.js'
|
||||
@ -36,6 +37,7 @@ export default {
|
||||
"clone": module_clone,
|
||||
"commit": module_commit,
|
||||
"config": module_config,
|
||||
"fetch": module_fetch,
|
||||
"help": module_help,
|
||||
"init": module_init,
|
||||
"log": module_log,
|
||||
|
88
packages/git/src/subcommands/fetch.js
Normal file
88
packages/git/src/subcommands/fetch.js
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Puter Technologies Inc.
|
||||
*
|
||||
* This file is part of Puter's Git client.
|
||||
*
|
||||
* Puter's Git client is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import git from 'isomorphic-git';
|
||||
import http from 'isomorphic-git/http/web';
|
||||
import { determine_fetch_remote, find_repo_root, PROXY_URL } from '../git-helpers.js';
|
||||
import { SHOW_USAGE } from '../help.js';
|
||||
|
||||
export default {
|
||||
name: 'fetch',
|
||||
usage: [
|
||||
'git fetch <repository>',
|
||||
'git fetch --all',
|
||||
],
|
||||
description: `Download objects and refs from another repository.`,
|
||||
args: {
|
||||
allowPositionals: true,
|
||||
options: {
|
||||
all: {
|
||||
description: 'Fetch all remotes.',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
},
|
||||
execute: async (ctx) => {
|
||||
const { io, fs, env, args } = ctx;
|
||||
const { stdout, stderr } = io;
|
||||
const { options, positionals } = args;
|
||||
const cache = {};
|
||||
|
||||
const { repository_dir, git_dir } = await find_repo_root(fs, env.PWD);
|
||||
|
||||
// TODO: Support <refspec> syntax.
|
||||
|
||||
const remotes = await git.listRemotes({
|
||||
fs,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
});
|
||||
|
||||
if (options.all) {
|
||||
for (const { remote, url } of remotes) {
|
||||
stdout(`Fetching ${remote}\nFrom ${url}`);
|
||||
await git.fetch({
|
||||
fs,
|
||||
http,
|
||||
cache,
|
||||
corsProxy: PROXY_URL,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
remote,
|
||||
onMessage: (message) => { stdout(message); },
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const remote = positionals.shift();
|
||||
const remote_data = determine_fetch_remote(remote, remotes);
|
||||
|
||||
await git.fetch({
|
||||
fs,
|
||||
http,
|
||||
cache,
|
||||
corsProxy: PROXY_URL,
|
||||
dir: repository_dir,
|
||||
gitdir: git_dir,
|
||||
...remote_data,
|
||||
onMessage: (message) => { stdout(message); },
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user