diff --git a/apps/remix-ide/src/app/files/dgitProvider.ts b/apps/remix-ide/src/app/files/dgitProvider.ts index 8dbc8e9376..a3a3a000af 100644 --- a/apps/remix-ide/src/app/files/dgitProvider.ts +++ b/apps/remix-ide/src/app/files/dgitProvider.ts @@ -4,26 +4,14 @@ import { Plugin } from '@remixproject/engine' import git, { ReadBlobResult, ReadCommitResult, StatusRow } from 'isomorphic-git' -import IpfsHttpClient from 'ipfs-http-client' -import { - saveAs -} from 'file-saver' -import http from 'isomorphic-git/http/web' - -import JSZip from 'jszip' import path from 'path' -import FormData from 'form-data' import axios from 'axios' import { Registry } from '@remix-project/remix-lib' -import { Octokit, App } from "octokit" -import { OctokitResponse } from '@octokit/types' -import { Endpoints } from "@octokit/types" +import { Octokit } from "octokit" import { IndexedDBStorage } from './filesystems/indexedDB' -import { GitHubUser, branch, commitChange, remote, userEmails } from '@remix-ui/git' -import { checkoutInputType, statusInput, logInputType, author, pagedCommits, remoteCommitsInputType, cloneInputType, fetchInputType, pullInputType, pushInputType, currentBranchInput, branchInputType, addInputType, rmInputType, resolveRefInput, readBlobInput, repositoriesInput, commitInputType, branchDifference, compareBranchesInput, initInputType, isoGitConfig} from '@remix-api' -import { LibraryProfile, StatusEvents } from '@remixproject/plugin-utils' -import { ITerminal } from '@remixproject/plugin-api/src/lib/terminal' -import { partial } from 'lodash' +import { branch, commitChange, remote } from '@remix-ui/git' +import { checkoutInputType, statusInput, logInputType, author, pagedCommits, remoteCommitsInputType, cloneInputType, fetchInputType, pullInputType, pushInputType, currentBranchInput, branchInputType, addInputType, rmInputType, resolveRefInput, readBlobInput, repositoriesInput, commitInputType, branchDifference, compareBranchesInput, initInputType, isoGitFSConfig, GitHubUser, userEmails } from '@remix-api' +import { LibraryProfile } from '@remixproject/plugin-utils' import { CustomRemixApi } from '@remix-api' import { isoGit } from "libs/remix-git/src/isogit" @@ -37,49 +25,17 @@ const profile: LibraryProfile = { description: 'Decentralized git provider', icon: 'assets/img/fileManager.webp', version: '0.0.1', - methods: ['init', 'localStorageUsed', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'rm', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pull', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'version', 'updateSubmodules' + methods: ['init', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'status', 'log', 'commit', 'add', 'remove', 'rm', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pull', 'version', 'updateSubmodules' , 'getGitHubUser', 'remotebranches', 'remotecommits', 'repositories', 'getCommitChanges', 'compareBranches'], kind: 'file-system' } class DGitProvider extends Plugin { - ipfsconfig: { host: string; port: number; protocol: string; ipfsurl: string } - globalIPFSConfig: { host: string; port: number; protocol: string; ipfsurl: string } - remixIPFS: { host: string; port: number; protocol: string; ipfsurl: string } - ipfsSources: any[] - ipfs: any - filesToSend: any[] constructor() { super(profile) - this.ipfsconfig = { - host: 'jqgt.remixproject.org', - port: 443, - protocol: 'https', - ipfsurl: 'https://jqgt.remixproject.org/ipfs/' - } - this.globalIPFSConfig = { - host: 'ipfs.io', - port: 443, - protocol: 'https', - ipfsurl: 'https://ipfs.io/ipfs/' - } - this.remixIPFS = { - host: 'jqgt.remixproject.org', - port: 443, - protocol: 'https', - ipfsurl: 'https://jqgt.remixproject.org/ipfs/' - } - this.ipfsSources = [this.remixIPFS, this.globalIPFSConfig, this.ipfsconfig] } async addIsomorphicGitConfigFS(dir = '') { - if ((Registry.getInstance().get('platform').api.isDesktop())) { - return { - fs: window.remixFileSystem, - dir: '/' - } - } - const workspace = await this.call('filePanel', 'getCurrentWorkspace') if (!workspace) return @@ -89,61 +45,12 @@ class DGitProvider extends Plugin { } } - async addIsomorphicGitConfig(input) { - - const token = await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token') - - let config = { - corsProxy: 'https://corsproxy.remixproject.org/', - http, - onAuth: url => { - url - const auth = { - username: input.token || token, - password: '' - } - return auth - } - } - if (input.url) { - - const url = new URL(input.url) - if (url.hostname.includes('localhost')) { - config = { - ...config, - corsProxy: null - } - } - } - if ((input.remote && input.remote.url)) { - - const url = new URL(input.remote.url) - if (url.hostname.includes('localhost')) { - config = { - ...config, - corsProxy: null, - } - } - } - - if (input.provider && input.provider === 'github') { - config = { - ...config, - corsProxy: 'https://corsproxy.remixproject.org/', - } - } - - if (input.provider && input.provider === 'localhost') { - config = { - ...config, - corsProxy: null - } - } - - return config + async getToken() { + return await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token') } - async getCommandUser(input) { + + async getAuthor(input) { const author: author = { name: '', email: '' @@ -306,10 +213,10 @@ class DGitProvider extends Plugin { async getCommitChanges(commitHash1: string, commitHash2: string): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { - const result = this.call('isogit', 'getCommitChanges', commitHash1, commitHash2 ) + const result = this.call('isogit', 'getCommitChanges', commitHash1, commitHash2) return result } - + return await isoGit.getCommitChanges(commitHash1, commitHash2, await this.addIsomorphicGitConfigFS()) } @@ -351,7 +258,7 @@ class DGitProvider extends Plugin { return await isoGit.currentbranch(input, defaultConfig) } - async branches(config: isoGitConfig): Promise { + async branches(config: isoGitFSConfig): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { const branches = await this.call('isogit', 'branches') @@ -416,22 +323,6 @@ class DGitProvider extends Plugin { return readBlobResult } - async setIpfsConfig(config) { - this.ipfsconfig = config - return new Promise((resolve) => { - resolve(this.checkIpfsConfig()) - }) - } - - async checkIpfsConfig(config?) { - this.ipfs = IpfsHttpClient(config || this.ipfsconfig) - try { - await this.ipfs.config.getAll() - return true - } catch (e) { - return false - } - } async addremote(input: remote): Promise { if ((Registry.getInstance().get('platform').api.isDesktop())) { @@ -449,10 +340,6 @@ class DGitProvider extends Plugin { await git.deleteRemote({ ...await this.addIsomorphicGitConfigFS(), remote: input.name }) } - async localStorageUsed() { - return this.calculateLocalStorage() - } - async clone(input: cloneInputType) { if ((Registry.getInstance().get('platform').api.isDesktop())) { @@ -481,14 +368,13 @@ class DGitProvider extends Plugin { } else { const permission = await this.askUserPermission('clone', 'Import multiple files into your workspaces.') if (!permission) return false - if (parseFloat(this.calculateLocalStorage()) > 10000) throw new Error('The local storage of the browser is full.') if (!input.workspaceExists) await this.call('filePanel', 'createWorkspace', input.workspaceName || `workspace_${Date.now()}`, true) const cmd = { url: input.url, singleBranch: input.singleBranch, ref: input.branch, depth: input.depth || 10, - ...await this.addIsomorphicGitConfig(input), + ...await isoGit.addIsomorphicGitProxyConfig(input, this), ...await this.addIsomorphicGitConfigFS() } this.call('terminal', 'logHtml', `Cloning ${input.url}... please wait...`) @@ -575,10 +461,10 @@ class DGitProvider extends Plugin { url: module.url, singleBranch: true, depth: 1, - ...await this.addIsomorphicGitConfig({ + ...await isoGit.addIsomorphicGitProxyConfig({ ...input, - provider: 'github' - }), + provider: 'github', + }, this), ...await this.addIsomorphicGitConfigFS(dir) } this.call('terminal', 'logHtml', `Cloning submodule ${dir}...`) @@ -602,10 +488,10 @@ class DGitProvider extends Plugin { if (result && result.length) { this.call('terminal', 'logHtml', `Checking out submodule ${dir} to ${result[0]} in directory ${dir}`) await git.fetch({ - ...await this.addIsomorphicGitConfig({ + ...await isoGit.addIsomorphicGitProxyConfig({ ...input, - provider: 'github' - }), + provider: 'github', + }, this), ...await this.addIsomorphicGitConfigFS(dir), singleBranch: true, ref: result[0] @@ -652,61 +538,23 @@ class DGitProvider extends Plugin { async push(input: pushInputType) { - const cmd = { - force: input.force, - ref: input.ref.name, - remoteRef: input.remoteRef && input.remoteRef.name, - remote: input.remote.name, - author: await this.getCommandUser(input), - input, - } if ((Registry.getInstance().get('platform').api.isDesktop())) { - return await this.call('isogit', 'push', { - ...input, - author: await this.getCommandUser(input), - }) + return await this.call('isogit', 'push', input) } else { - - const cmd2 = { - ...cmd, - ...await this.addIsomorphicGitConfig(input), - } - - const result = await git.push({ - ...await this.addIsomorphicGitConfigFS(), - ...cmd2 - }) - + const result = await isoGit.push(input, await this.addIsomorphicGitConfigFS(), this) return result - } } async pull(input: pullInputType) { - const cmd = { - ref: input.ref.name, - remoteRef: input.remoteRef && input.remoteRef.name, - author: await this.getCommandUser(input), - remote: input.remote.name, - input, - } + let result if ((Registry.getInstance().get('platform').api.isDesktop())) { - result = await this.call('isogit', 'pull', { - ...input, - author: await this.getCommandUser(input), - }) + result = await this.call('isogit', 'pull', input) } else { - const cmd2 = { - ...cmd, - ...await this.addIsomorphicGitConfig(input), - } - result = await git.pull({ - ...await this.addIsomorphicGitConfigFS(), - ...cmd2 - }) + result = await isoGit.pull(input, await this.addIsomorphicGitConfigFS(), this) } setTimeout(async () => { await this.call('fileManager', 'refresh') @@ -715,33 +563,15 @@ class DGitProvider extends Plugin { } async fetch(input: fetchInputType) { - const cmd = { - ref: input.ref && input.ref.name, - remoteRef: input.remoteRef && input.remoteRef.name, - author: await this.getCommandUser(input), - remote: input.remote && input.remote.name, - depth: input.depth || 5, - singleBranch: input.singleBranch, - relative: input.relative, - input - } + let result if ((Registry.getInstance().get('platform').api.isDesktop())) { result = await this.call('isogit', 'fetch', { ...input, - author: await this.getCommandUser(input), }) } else { - const cmd2 = { - ...cmd, - ...await this.addIsomorphicGitConfig(input), - } - result = await git.fetch({ - ...await this.addIsomorphicGitConfigFS(), - ...cmd2 - }) - + result = await isoGit.fetch(input, await this.addIsomorphicGitConfigFS(), this) } setTimeout(async () => { @@ -750,162 +580,6 @@ class DGitProvider extends Plugin { return result } - async export(config) { - if (!this.checkIpfsConfig(config)) return false - const workspace = await this.call('filePanel', 'getCurrentWorkspace') - const files = await this.getDirectory('/') - this.filesToSend = [] - for (const file of files) { - const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`, null) - const ob = { - path: file, - content: c - } - this.filesToSend.push(ob) - } - const addOptions = { - wrapWithDirectory: true - } - const r = await this.ipfs.add(this.filesToSend, addOptions) - return r.cid.string - } - - async importIPFSFiles(config, cid, workspace) { - const ipfs = IpfsHttpClient(config) - let result = false - try { - const data = ipfs.get(cid, { timeout: 60000 }) - for await (const file of data) { - if (file.path) result = true - file.path = file.path.replace(cid, '') - if (!file.content) { - continue - } - const content = [] - for await (const chunk of file.content) { - content.push(chunk) - } - const dir = path.dirname(file.path) - try { - await this.createDirectories(`${workspace.absolutePath}/${dir}`) - } catch (e) { throw new Error(e) } - try { - await window.remixFileSystem.writeFile(`${workspace.absolutePath}/${file.path}`, Buffer.concat(content) || new Uint8Array(), null) - } catch (e) { throw new Error(e) } - } - } catch (e) { - throw new Error(e) - } - return result - } - - calculateLocalStorage() { - let _lsTotal = 0 - let _xLen; let _x - for (_x in localStorage) { - // eslint-disable-next-line no-prototype-builtins - if (!localStorage.hasOwnProperty(_x)) { - continue - } - _xLen = ((localStorage[_x].length + _x.length) * 2) - _lsTotal += _xLen - } - return (_lsTotal / 1024).toFixed(2) - } - - async import(cmd) { - const permission = await this.askUserPermission('import', 'Import multiple files into your workspaces.') - if (!permission) return false - if (parseFloat(this.calculateLocalStorage()) > 10000) throw new Error('The local storage of the browser is full.') - const cid = cmd.cid - await this.call('filePanel', 'createWorkspace', `workspace_${Date.now()}`, true) - const workspace = await this.call('filePanel', 'getCurrentWorkspace') - let result - if (cmd.local) { - result = await this.importIPFSFiles(this.ipfsconfig, cid, workspace) - } else { - result = await this.importIPFSFiles(this.remixIPFS, cid, workspace) || await this.importIPFSFiles(this.ipfsconfig, cid, workspace) || await this.importIPFSFiles(this.globalIPFSConfig, cid, workspace) - } - setTimeout(async () => { - await this.call('fileManager', 'refresh') - }, 1000) - if (!result) throw new Error(`Cannot pull files from IPFS at ${cid}`) - } - - async getItem(name) { - if (typeof window !== 'undefined') { - return window.localStorage.getItem(name) - } - } - - async setItem(name, content) { - try { - if (typeof window !== 'undefined') { - window.localStorage.setItem(name, content) - } - } catch (e) { - console.log(e) - return false - } - return true - } - - async zip() { - const zip = new JSZip() - const workspace = await this.call('filePanel', 'getCurrentWorkspace') - const files = await this.getDirectory('/') - this.filesToSend = [] - for (const file of files) { - const c = await window.remixFileSystem.readFile(`${workspace.absolutePath}/${file}`, null) - zip.file(file, c) - } - await zip.generateAsync({ - type: 'blob' - }) - .then(function (content) { - saveAs(content, `${workspace.name}.zip`) - }) - } - - async createDirectories(strdirectories) { - const ignore = ['.', '/.', ''] - if (ignore.indexOf(strdirectories) > -1) return false - const directories = strdirectories.split('/') - for (let i = 0; i < directories.length; i++) { - let previouspath = '' - if (i > 0) previouspath = '/' + directories.slice(0, i).join('/') - const finalPath = previouspath + '/' + directories[i] - try { - if (!await window.remixFileSystem.exists(finalPath)) { - await window.remixFileSystem.mkdir(finalPath) - } - } catch (e) { - console.log(e) - } - } - } - - async getDirectory(dir) { - let result = [] - const files = await this.call('fileManager', 'readdir', dir) - const fileArray = normalize(files) - for (const fi of fileArray) { - if (fi) { - const type = fi.data.isDirectory - if (type === true) { - result = [ - ...result, - ...(await this.getDirectory( - `${fi.filename}` - )) - ] - } else { - result = [...result, fi.filename] - } - } - } - return result - } // OCTOKIT FEATURES @@ -1042,23 +716,4 @@ const addSlash = (file) => { return file } -const normalize = (filesList) => { - const folders = [] - const files = [] - Object.keys(filesList || {}).forEach(key => { - if (filesList[key].isDirectory) { - folders.push({ - filename: key, - data: filesList[key] - }) - } else { - files.push({ - filename: key, - data: filesList[key] - }) - } - }) - return [...folders, ...files] -} - module.exports = DGitProvider diff --git a/apps/remixdesktop/src/plugins/isoGitPlugin.ts b/apps/remixdesktop/src/plugins/isoGitPlugin.ts index 3272696e77..430928e3ff 100644 --- a/apps/remixdesktop/src/plugins/isoGitPlugin.ts +++ b/apps/remixdesktop/src/plugins/isoGitPlugin.ts @@ -5,7 +5,7 @@ import git from 'isomorphic-git' import http from 'isomorphic-git/http/web' import { gitProxy } from "../tools/git"; import { isoGit } from "@remix-git" -import { branch, branchDifference, branchInputType, cloneInputType, commitChange, commitInputType, compareBranchesInput, currentBranchInput, fetchInputType, initInputType, logInputType, pullInputType, pushInputType, remote, resolveRefInput, statusInput } from "@remix-api"; +import { branchDifference, branchInputType, cloneInputType, commitChange, commitInputType, compareBranchesInput, currentBranchInput, fetchInputType, initInputType, logInputType, pullInputType, pushInputType, remote, resolveRefInput, statusInput } from "@remix-api"; const profile: Profile = { name: 'isogit', @@ -28,20 +28,6 @@ export class IsoGitPlugin extends ElectronBasePlugin { } } -const parseInput = (input: any) => { - return { - corsProxy: 'https://corsproxy.remixproject.org/', - http, - onAuth: (url: any) => { - url - const auth = { - username: input.token, - password: '' - } - return auth - } - } -} const clientProfile: Profile = { name: 'isogit', @@ -58,10 +44,10 @@ class IsoGitPluginClient extends ElectronBasePluginClient { this.onload(async () => { this.on('fs' as any, 'workingDirChanged', async (path: string) => { this.workingDir = path - this.gitIsInstalled = await gitProxy.version() ? true : false + this.gitIsInstalled = await gitProxy.version() ? true : false }) this.workingDir = await this.call('fs' as any, 'getWorkingDir') - this.gitIsInstalled = await gitProxy.version() && !useIsoGit ? true : false + this.gitIsInstalled = await gitProxy.version() && !useIsoGit ? true : false }) } @@ -102,6 +88,8 @@ class IsoGitPluginClient extends ElectronBasePluginClient { async log(cmd: logInputType) { console.log('LOG', cmd) + const token = await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token') + console.log('LOG', token) /* we will use isomorphic git for now if(this.gitIsInstalled){ const log = await gitProxy.log(this.workingDir, cmd.ref) @@ -237,66 +225,46 @@ class IsoGitPluginClient extends ElectronBasePluginClient { return checkout } - async push(cmd: pushInputType) { - + async push(input: pushInputType) { + console.log('PUSH', input, this.gitIsInstalled) if (!this.workingDir || this.workingDir === '') { throw new Error('No working directory') } if (this.gitIsInstalled) { - await gitProxy.push(this.workingDir, cmd) - + return await gitProxy.push(this.workingDir, input) } else { - /* - const push = await git.push({ - ...await this.getGitConfig(), - ...cmd, - ...parseInput(cmd.input) - }) - return push*/ + const push = await isoGit.push(input, await this.getGitConfig(), this) + return push } } - async pull(cmd: pullInputType) { - + async pull(input: pullInputType) { + console.log('PULL', input) if (!this.workingDir || this.workingDir === '') { throw new Error('No working directory') } if (this.gitIsInstalled) { - await gitProxy.pull(this.workingDir, cmd) - + return await gitProxy.pull(this.workingDir, input) } else { - /* - const pull = await git.pull({ - ...await this.getGitConfig(), - ...cmd, - ...parseInput(cmd.input) - }) - + const pull = await isoGit.pull(input, await this.getGitConfig(), this) return pull - */ } } - async fetch(cmd: fetchInputType) { - console.log('FETCH', cmd) + async fetch(input: fetchInputType) { + console.log('FETCH', input) if (!this.workingDir || this.workingDir === '') { throw new Error('No working directory') } if (this.gitIsInstalled) { - await gitProxy.fetch(this.workingDir, cmd) + await gitProxy.fetch(this.workingDir, input) } else { - /* - const fetch = await git.fetch({ - ...await this.getGitConfig(), - ...cmd, - ...parseInput(cmd.input) - }) - */ + const fetch = await isoGit.fetch(input, await this.getGitConfig(), this) return fetch } } diff --git a/libs/remix-api/src/lib/types/git.ts b/libs/remix-api/src/lib/types/git.ts index 7482e95a1d..50d145279b 100644 --- a/libs/remix-api/src/lib/types/git.ts +++ b/libs/remix-api/src/lib/types/git.ts @@ -1,4 +1,5 @@ -import { ReadCommitResult } from "isomorphic-git" +import { Endpoints } from "@octokit/types" +import { AuthCallback, HttpClient, ReadCommitResult } from "isomorphic-git" export type branchDifference = { uniqueHeadCommits: ReadCommitResult[], @@ -71,7 +72,7 @@ export type initInputType = { export type author = { name: string, - email: string + email: string, } export type updateSubmodulesInput = { @@ -96,6 +97,7 @@ export type fetchInputType = { relative?: boolean, quiet?: boolean author?: author + token?: string } export type logInputType = { @@ -108,6 +110,7 @@ export type pullInputType = { ref: branch, remoteRef?: branch author?: author + token?: string } export type pushInputType = { @@ -115,7 +118,8 @@ export type pushInputType = { ref: branch, remoteRef?: branch, force?: boolean, - author?: author + author?: author, + token?: string } export type branchInputType = { @@ -183,7 +187,16 @@ export interface repositoriesInput { token: string, page?: number, per_page?: nu export interface statusInput { ref: string, filepaths?: string[] } -export type isoGitConfig = { +export type isoGitFSConfig = { fs: any, dir: string, -} \ No newline at end of file +} + +export type isoGitProxyConfig = { + corsProxy: string + http: HttpClient + onAuth: AuthCallback +} + +export type GitHubUser = Partial +export type userEmails = Endpoints["GET /user/emails"]["response"]["data"] \ No newline at end of file diff --git a/libs/remix-git/src/isogit.ts b/libs/remix-git/src/isogit.ts index bd3b608203..6e6b11bf83 100644 --- a/libs/remix-git/src/isogit.ts +++ b/libs/remix-git/src/isogit.ts @@ -1,159 +1,329 @@ -import { branch, commitChange, compareBranchesInput, currentBranchInput, isoGitConfig, remote } from "@remix-api" +import { GitHubUser, author, branch, commitChange, compareBranchesInput, currentBranchInput, fetchInputType, isoGitFSConfig, isoGitProxyConfig, pullInputType, pushInputType, remote, userEmails } from "@remix-api" import git from 'isomorphic-git' +import { + Plugin +} from '@remixproject/engine' +import http from 'isomorphic-git/http/web' -const currentbranch = async (input: currentBranchInput, defaultConfig: isoGitConfig ) => { - console.log('CURRENT BRANCH', input) +import { Octokit } from "octokit" +import { ElectronBasePluginClient } from "@remixproject/plugin-electron" +const currentbranch = async (input: currentBranchInput, fsConfig: isoGitFSConfig) => { + console.log('CURRENT BRANCH', input) + try { + const cmd = input ? fsConfig ? { ...fsConfig, ...input } : input : fsConfig + + const name = await git.currentBranch(cmd) + let remote: remote = undefined try { - const cmd = input ? defaultConfig ? { ...defaultConfig, ...input } : input : defaultConfig - - const name = await git.currentBranch(cmd) - let remote: remote = undefined - try { - const remoteName = await git.getConfig({ - ...defaultConfig, - path: `branch.${name}.remote` + const remoteName = await git.getConfig({ + ...fsConfig, + path: `branch.${name}.remote` + }) + if (remoteName) { + const remoteUrl = await git.getConfig({ + ...fsConfig, + path: `remote.${remoteName}.url` }) - if (remoteName) { - const remoteUrl = await git.getConfig({ - ...defaultConfig, - path: `remote.${remoteName}.url` - }) - remote = { name: remoteName, url: remoteUrl } - } + remote = { name: remoteName, url: remoteUrl } + } - } catch (e) { - // do nothing + } catch (e) { + // do nothing + } + console.log('NAME', name) + console.log('REMOTE', remote) + + return { + remote: remote, + name: name || '' + } + } catch (e) { + return undefined + } +} + +const branches = async (fsConfig: isoGitFSConfig) => { + try { + + const remotes = await isoGit.remotes(fsConfig) + let branches: branch[] = [] + branches = (await git.listBranches(fsConfig)).map((branch) => { return { remote: undefined, name: branch } }) + for (const remote of remotes) { + const cmd = { + ...fsConfig, + remote: remote.name } - console.log('NAME', name) - console.log('REMOTE', remote) - - return { - remote: remote, - name: name || '' + const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote, name: branch } }) + branches = [...branches, ...remotebranches] + } + return branches + } catch (e) { + console.log(e) + return [] + } +} + +const remotes = async (fsConfig: isoGitFSConfig) => { + + let remotes: remote[] = [] + try { + remotes = (await git.listRemotes({ ...fsConfig })).map((remote) => { return { name: remote.remote, url: remote.url } } + ) + } catch (e) { + // do nothing + } + return remotes +} + +const push = async (input: pushInputType, fsConfig: isoGitFSConfig, plugin: Plugin | ElectronBasePluginClient) => { + const cmd = { + force: input.force, + ref: input.ref.name, + remoteRef: input.remoteRef && input.remoteRef.name, + remote: input.remote.name, + author: await getAuthor(input, plugin), + input, + } + + const proxy = await isoGit.addIsomorphicGitProxyConfig(input, plugin) + console.log({ ...fsConfig, ...cmd, ...proxy }) + return await git.push({ ...fsConfig, ...cmd, ...proxy }) +} + +const pull = async (input: pullInputType, fsConfig: isoGitFSConfig, plugin: Plugin | ElectronBasePluginClient) => { + const cmd = { + ref: input.ref.name, + remoteRef: input.remoteRef && input.remoteRef.name, + author: await getAuthor(input, plugin), + remote: input.remote.name, + input, + } + const proxy = await isoGit.addIsomorphicGitProxyConfig(input, plugin) + console.log({ ...fsConfig, ...cmd, ...proxy }) + return await git.pull({ ...fsConfig, ...cmd, ...proxy }) +} + +const fetch = async (input: fetchInputType, fsConfig: isoGitFSConfig, plugin: Plugin | ElectronBasePluginClient) => { + const cmd = { + ref: input.ref && input.ref.name, + remoteRef: input.remoteRef && input.remoteRef.name, + author: await getAuthor(input, plugin), + remote: input.remote && input.remote.name, + depth: input.depth || 5, + singleBranch: input.singleBranch, + relative: input.relative, + input + } + const proxy = await isoGit.addIsomorphicGitProxyConfig(input, plugin) + console.log({ ...fsConfig, ...cmd, ...proxy }) + return await git.fetch({ ...fsConfig, ...cmd, ...proxy }) +} + +const getAuthor = async (input, plugin: any) => { + const author: author = { + name: '', + email: '' + } + if (input && input.name && input.email) { + author.name = input.name + author.email = input.email + } else { + const username = await plugin.call('config' as any, 'getAppParameter', 'settings/github-user-name') + const email = await plugin.call('config' as any, 'getAppParameter', 'settings/github-email') + const token = await plugin.call('config' as any, 'getAppParameter', 'settings/gist-access-token') + if (username && email) { + author.name = username + author.email = email + } else if (token) { + + const gitHubUser = await isoGit.getGitHubUser({ token }) + + if (gitHubUser) { + author.name = gitHubUser.user.login } - } catch (e) { - return undefined } } + return author +} - const branches = async (defaultConfig: isoGitConfig ) => { - try { - const remotes = await isoGit.remotes(defaultConfig) - let branches: branch[] = [] - branches = (await git.listBranches(defaultConfig)).map((branch) => { return { remote: undefined, name: branch } }) - for (const remote of remotes) { - const cmd = { - ...defaultConfig, - remote: remote.name - } - const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote, name: branch } }) - branches = [...branches, ...remotebranches] +const getGitHubUser = async (input: { token: string }): Promise<{ + user: GitHubUser, + emails: userEmails, + scopes: string[] +}> => { + try { + const octokit = new Octokit({ + auth: input.token + }) + + const user = await octokit.request('GET /user') + const emails = await octokit.request('GET /user/emails') + + const scopes = user.headers['x-oauth-scopes'] || '' + + console.log('USER', user.data) + + return { + user: user.data, + emails: emails.data, + scopes: scopes && scopes.split(',') + } + } catch (e) { + return null + } +} + +const addIsomorphicGitProxyConfig = async (input: { + url?: string, + remote?: remote, + provider?: 'github' | 'localhost', + token?: string, +}, plugin: any) => { + + const token = await plugin.call('config' as any, 'getAppParameter', 'settings/gist-access-token') + console.log('TOKEN', token) + + let config: isoGitProxyConfig = { + corsProxy: 'https://corsproxy.remixproject.org/', + http, + onAuth: url => { + url + const auth = { + username: input.token || token, + password: '' } - return branches - } catch (e) { - console.log(e) - return [] + return auth } } + if (input.url) { - const remotes = async(defaultConfig: isoGitConfig) => { + const url = new URL(input.url) + if (url.hostname.includes('localhost')) { + config = { + ...config, + corsProxy: null + } + } + } + if ((input.remote && input.remote.url)) { - let remotes: remote[] = [] - try { - remotes = (await git.listRemotes({ ...defaultConfig })).map((remote) => { return { name: remote.remote, url: remote.url } } - ) - } catch (e) { - // do nothing + const url = new URL(input.remote.url) + if (url.hostname.includes('localhost')) { + config = { + ...config, + corsProxy: null, + } + } + } + + if (input.provider && input.provider === 'github') { + config = { + ...config, + corsProxy: 'https://corsproxy.remixproject.org/', } - return remotes } - const getCommitChanges = async (commitHash1: string, commitHash2: string, defaultConfig: isoGitConfig) => { - const result: commitChange[] = await git.walk({ - ...defaultConfig, - trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })], - map: async function (filepath, [A, B]) { + if (input.provider && input.provider === 'localhost') { + config = { + ...config, + corsProxy: null + } + } + + return config +} + +const getCommitChanges = async (commitHash1: string, commitHash2: string, fsConfig: isoGitFSConfig) => { + const result: commitChange[] = await git.walk({ + ...fsConfig, + trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })], + map: async function (filepath, [A, B]) { - if (filepath === '.') { + if (filepath === '.') { + return + } + try { + if ((A && await A.type()) === 'tree' || B && (await B.type()) === 'tree') { return } - try { - if ((A && await A.type()) === 'tree' || B && (await B.type()) === 'tree') { - return - } - } catch (e) { - // ignore - } + } catch (e) { + // ignore + } - // generate ids - const Aoid = A && await A.oid() || undefined - const Boid = B && await B.oid() || undefined + // generate ids + const Aoid = A && await A.oid() || undefined + const Boid = B && await B.oid() || undefined - const commitChange: Partial = { - hashModified: commitHash1, - hashOriginal: commitHash2, - path: filepath, - } + const commitChange: Partial = { + hashModified: commitHash1, + hashOriginal: commitHash2, + path: filepath, + } - // determine modification type - if (Aoid !== Boid) { - commitChange.type = "modified" - } - if (Aoid === undefined) { - commitChange.type = "deleted" - } - if (Boid === undefined || !commitHash2) { - commitChange.type = "added" - } - if (Aoid === undefined && Boid === undefined) { - commitChange.type = "unknown" - } - if (commitChange.type) - return commitChange - else - return undefined - }, - }) + // determine modification type + if (Aoid !== Boid) { + commitChange.type = "modified" + } + if (Aoid === undefined) { + commitChange.type = "deleted" + } + if (Boid === undefined || !commitHash2) { + commitChange.type = "added" + } + if (Aoid === undefined && Boid === undefined) { + commitChange.type = "unknown" + } + if (commitChange.type) + return commitChange + else + return undefined + }, + }) - return result - } + return result +} - const compareBranches = async ({ branch, remote }: compareBranchesInput, defaultConfig: isoGitConfig) => { +const compareBranches = async ({ branch, remote }: compareBranchesInput, fsConfig: isoGitFSConfig) => { - // Get current branch commits - const headCommits = await git.log({ - ...defaultConfig, - ref: branch.name, - }); + // Get current branch commits + const headCommits = await git.log({ + ...fsConfig, + ref: branch.name, + }); - // Get remote branch commits - const remoteCommits = await git.log({ - ...defaultConfig, - ref: `${remote.name}/${branch.name}`, - }); + // Get remote branch commits + const remoteCommits = await git.log({ + ...fsConfig, + ref: `${remote.name}/${branch.name}`, + }); - // Convert arrays of commit objects to sets of commit SHAs - const headCommitSHAs = new Set(headCommits.map(commit => commit.oid)); - const remoteCommitSHAs = new Set(remoteCommits.map(commit => commit.oid)); + // Convert arrays of commit objects to sets of commit SHAs + const headCommitSHAs = new Set(headCommits.map(commit => commit.oid)); + const remoteCommitSHAs = new Set(remoteCommits.map(commit => commit.oid)); - // Filter out commits that are only in the remote branch - const uniqueRemoteCommits = remoteCommits.filter(commit => !headCommitSHAs.has(commit.oid)); + // Filter out commits that are only in the remote branch + const uniqueRemoteCommits = remoteCommits.filter(commit => !headCommitSHAs.has(commit.oid)); - // filter out commits that are only in the local branch - const uniqueHeadCommits = headCommits.filter(commit => !remoteCommitSHAs.has(commit.oid)); + // filter out commits that are only in the local branch + const uniqueHeadCommits = headCommits.filter(commit => !remoteCommitSHAs.has(commit.oid)); - return { - uniqueHeadCommits, - uniqueRemoteCommits, - }; - } + return { + uniqueHeadCommits, + uniqueRemoteCommits, + }; +} - export const isoGit = { - currentbranch, - remotes, - branches, - getCommitChanges, - compareBranches - } \ No newline at end of file +export const isoGit = { + currentbranch, + remotes, + branches, + getCommitChanges, + compareBranches, + addIsomorphicGitProxyConfig, + push, + pull, + fetch, + getGitHubUser +} \ No newline at end of file diff --git a/libs/remix-ui/git/src/lib/gitactions.ts b/libs/remix-ui/git/src/lib/gitactions.ts index d27fe7b3f5..36651a4da9 100644 --- a/libs/remix-ui/git/src/lib/gitactions.ts +++ b/libs/remix-ui/git/src/lib/gitactions.ts @@ -1,13 +1,13 @@ import { ReadBlobResult, ReadCommitResult } from "isomorphic-git"; import React from "react"; import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog, setUserEmails, setCurrenHead } from "../state/gitpayload"; -import { GitHubUser, gitActionDispatch, statusMatrixType, gitState, gitLog, fileStatusResult, userEmails } from '../types'; +import { gitActionDispatch, statusMatrixType, gitState, gitLog, fileStatusResult } from '../types'; import { removeSlash } from "../utils"; import { disableCallBacks, enableCallBacks } from "./listeners"; import { ModalTypes } from "@remix-ui/app"; import { setFileDecorators } from "./pluginActions"; import { Plugin } from "@remixproject/engine"; -import { addInputType, branch, branchDifference, checkoutInputType, cloneInputType, commitChange, CustomRemixApi, fetchInputType, pullInputType, pushInputType, remote, rmInputType } from "@remix-api"; +import { addInputType, branch, branchDifference, checkoutInputType, cloneInputType, commitChange, CustomRemixApi, fetchInputType, GitHubUser, pullInputType, pushInputType, remote, rmInputType, userEmails } from "@remix-api"; import { file } from "jszip"; export const fileStatuses = [ diff --git a/libs/remix-ui/git/src/state/actions.ts b/libs/remix-ui/git/src/state/actions.ts index ce1134a388..94e8a1923b 100644 --- a/libs/remix-ui/git/src/state/actions.ts +++ b/libs/remix-ui/git/src/state/actions.ts @@ -1,6 +1,6 @@ import { ReadCommitResult } from "isomorphic-git" -import { fileStatusResult, GitHubUser, gitLog, userEmails } from "../types" -import { branch, branchDifference, commitChange, pagedCommits, remote, remoteBranch, repository } from '@remix-api' +import { fileStatusResult, gitLog } from "../types" +import { GitHubUser, branch, branchDifference, commitChange, pagedCommits, remote, remoteBranch, repository, userEmails } from '@remix-api' export interface ActionPayloadTypes { FILE_STATUS: fileStatusResult[], FILE_STATUS_MERGE: fileStatusResult[] diff --git a/libs/remix-ui/git/src/state/gitpayload.ts b/libs/remix-ui/git/src/state/gitpayload.ts index b07b5350aa..9e8a51dc5a 100644 --- a/libs/remix-ui/git/src/state/gitpayload.ts +++ b/libs/remix-ui/git/src/state/gitpayload.ts @@ -1,6 +1,6 @@ import { ReadCommitResult } from "isomorphic-git" -import { GitHubUser, fileStatusResult, gitLog, userEmails } from "../types" -import { repository, pagedCommits, branch, remote, commitChange, branchDifference } from "@remix-api" +import { fileStatusResult, gitLog } from "../types" +import { repository, pagedCommits, branch, remote, commitChange, branchDifference, GitHubUser, userEmails } from "@remix-api" export const fileStatus = (files: fileStatusResult[]) => { return { diff --git a/libs/remix-ui/git/src/types/index.ts b/libs/remix-ui/git/src/types/index.ts index b3b4de928d..6b3119a2d2 100644 --- a/libs/remix-ui/git/src/types/index.ts +++ b/libs/remix-ui/git/src/types/index.ts @@ -1,8 +1,6 @@ import { Endpoints } from "@octokit/types" -import { branch, branchDifference, commitChange, pagedCommits, remote, remoteBranch, repository, syncStatus } from "@remix-api" +import { GitHubUser, branch, branchDifference, commitChange, pagedCommits, remote, remoteBranch, repository, syncStatus, userEmails } from "@remix-api" import { ReadCommitResult } from "isomorphic-git" -export type GitHubUser = Partial -export type userEmails = Endpoints["GET /user/emails"]["response"]["data"] export type gitState = { currentBranch: branch