如何使用node.js克隆github仓库

问题描述 投票:0回答:4

我需要一种可靠的方法来克隆 github 存储库并使用 node.js 和任何必要的 npm 包将其粘贴到本地目录中。

此代码使用nodegit库,无法克隆github存储库。它创建一个名为 .git 的文件夹,并且不会从存储库中复制任何文件。我尝试过几个库,其中大多数都有极其复杂的代码或不起作用。这以前有效,但现在不行了。 (它随心所欲地打开和关闭)。请帮助,我需要一个可靠的代码,从 url 克隆 github 存储库并将其粘贴到本地目录中。谢谢。

var nodegit = require('nodegit'),
    path = require('path');

var url = "https://github.com/atomicptr/dauntless-builder", //also tried https://github.com/atomicptr/dauntless-builder.git
    local = "C:/data",
    cloneOpts = {};

nodegit.Clone(url, local, cloneOpts).then(function (repo) {
    console.log("cloning succesful!");
    console.log("Cloned " + path.basename(url) + " to " + repo.workdir());
}).catch(function (err) {
    console.log(err);
});

此代码没有显示任何错误,但实际上无法克隆存储库。

javascript node.js git github clone
4个回答
21
投票

您可以使用 shelljs 来实现此目的。

const shell = require('shelljs')
const path = 'absolute/path/to/folder'
shell.cd(path)
shell.exec('git clone https://github.com/atomicptr/dauntless-builder')

10
投票

假设您在计算机上安装了 git,您可以简单地从节点运行克隆命令。

const path = require('path');
const{ execSync } = require('child_process');

execSync('git clone repolink', {
  stdio: [0, 1, 2], // we need this so node will print the command output
  cwd: path.resolve(__dirname, ''), // path to where you want to save the file
})

7
投票

尝试 git-clone npm 包

npm i git-clone
var clone = require('git-clone');

clone(repo, targetPath, [options], cb);

支持的选项:

git:git 二进制文件的路径;默认:git(可选)。

shallow:当 true 时,克隆深度为 1(可选)。

签出:要签出的修订/分支/标签(可选)。


0
投票

我无法在我正在开发的 Linux 机器上安装 Git(在 Web 服务器上运行),因此遇到这个问题后,我编写了一个 NodeJS 脚本来使用 Git API 并执行此操作。老实说,这并没有那么疯狂 <100 lines. Also, it should work with vanilla node (which happened to be installed).

附注我已经在 Windows 和 Linux 上测试过它。

const fs = require('fs');
const path = require('path');
const https = require('https');

// Parse command-line arguments
const [repoOwner, repoName, branch] = process.argv.slice(2);

if (!repoOwner || !repoName || !branch) {
    console.error('Usage: node clone-repo.js <repoOwner> <repoName> <branch>');
    process.exit(1);
}

const baseUrl = `https://api.github.com/repos/${repoOwner}/${repoName}/contents`;

function fetchRepoContents(url) {
    return new Promise((resolve, reject) => {
        https.get(url, { headers: { 'User-Agent': 'node.js' } }, (res) => {
            let data = '';
            res.on('data', (chunk) => {
                data += chunk;
            });
            res.on('end', () => {
                resolve(JSON.parse(data));
            });
        }).on('error', (err) => {
            reject(err);
        });
    });
}

async function downloadFile(url, filePath) {
    return new Promise((resolve, reject) => {
        https.get(url, { headers: { 'User-Agent': 'node.js' } }, (res) => {
            const fileStream = fs.createWriteStream(filePath);
            res.pipe(fileStream);
            fileStream.on('finish', () => {
                fileStream.close();
                resolve();
            });
        }).on('error', (err) => {
            fs.unlink(filePath, () => {}); // Delete the file async. (avoid using callback)
            reject(err);
        });
    });
}

async function processContents(contents, basePath) {
    for (const item of contents) {
        const fullPath = path.join(basePath, item.name);
        if (item.type === 'dir') {
            fs.mkdirSync(fullPath, { recursive: true });
            console.log(`Created directory: ${fullPath}`);
            const dirContents = await fetchRepoContents(item.url);
            await processContents(dirContents, fullPath);
        } else if (item.type === 'file') {
            try {
                // Ensure the directory exists before downloading the file
                const dirPath = path.dirname(fullPath);
                if (!fs.existsSync(dirPath)) {
                    fs.mkdirSync(dirPath, { recursive: true });
                    console.log(`Created directory: ${dirPath}`);
                }
                await downloadFile(item.download_url, fullPath);
                console.log(`Downloaded file: ${fullPath}`);
            } catch (err) {
                console.error(`Error downloading file ${fullPath}:`, err);
            }
        } else {
            console.warn(`Unknown type for ${fullPath}: ${item.type}`);
        }
    }
}

async function main() {
    try {
        const contents = await fetchRepoContents(`${baseUrl}?ref=${branch}`);
        await processContents(contents, repoName);
        console.log('Repository cloned successfully');
    } catch (err) {
        console.error('Error cloning repository:', err);
    }
}

main();

用途:

node clone-repo.js repoOwner repoName branch
© www.soinside.com 2019 - 2024. All rights reserved.