use native git

rdesktop2
bunsenstraat 1 year ago
parent fe86f5927b
commit dc8cf19bf1
  1. 12
      apps/remix-ide/src/app/plugins/electron/isoGitPlugin.ts
  2. 3
      apps/remixdesktop/src/engine.ts
  3. 36
      apps/remixdesktop/src/plugins/gitPlugin.ts
  4. 39
      apps/remixdesktop/src/plugins/isoGitPlugin.ts
  5. 133
      apps/remixdesktop/src/tools/git.ts
  6. 1
      libs/remix-ui/workspace/src/lib/actions/index.ts

@ -11,8 +11,18 @@ export class isoGitPlugin extends ElectronPlugin {
} }
onActivation(): void { async onActivation(): Promise<void> {
setTimeout(async () => {
const version = await this.call('isogit', 'version')
if(version){
this.call('terminal', 'log', version)
}else{
this.call('terminal', 'log', 'Git is not installed on the system. Using builtin git instead. Performance will be affected. It is better to install git on the system and configure the credentials to connect to GitHub etc.')
}
}, 5000)
} }

@ -1,7 +1,6 @@
import { Engine, PluginManager } from '@remixproject/engine'; import { Engine, PluginManager } from '@remixproject/engine';
import { ipcMain } from 'electron'; import { ipcMain } from 'electron';
import { FSPlugin } from './plugins/fsPlugin'; import { FSPlugin } from './plugins/fsPlugin';
import { GitPlugin } from './plugins/gitPlugin';
import { app } from 'electron'; import { app } from 'electron';
import { XtermPlugin } from './plugins/xtermPlugin'; import { XtermPlugin } from './plugins/xtermPlugin';
import git from 'isomorphic-git' import git from 'isomorphic-git'
@ -12,14 +11,12 @@ import { TemplatesPlugin } from './plugins/templates';
const engine = new Engine() const engine = new Engine()
const appManager = new PluginManager() const appManager = new PluginManager()
const fsPlugin = new FSPlugin() const fsPlugin = new FSPlugin()
const gitPlugin = new GitPlugin()
const xtermPlugin = new XtermPlugin() const xtermPlugin = new XtermPlugin()
const isoGitPlugin = new IsoGitPlugin() const isoGitPlugin = new IsoGitPlugin()
const configPlugin = new ConfigPlugin() const configPlugin = new ConfigPlugin()
const templatesPlugin = new TemplatesPlugin() const templatesPlugin = new TemplatesPlugin()
engine.register(appManager) engine.register(appManager)
engine.register(fsPlugin) engine.register(fsPlugin)
engine.register(gitPlugin)
engine.register(xtermPlugin) engine.register(xtermPlugin)
engine.register(isoGitPlugin) engine.register(isoGitPlugin)
engine.register(configPlugin) engine.register(configPlugin)

@ -1,36 +0,0 @@
import { PluginClient } from "@remixproject/plugin";
import { Profile } from "@remixproject/plugin-utils";
import { ElectronBasePlugin, ElectronBasePluginClient } from "@remixproject/plugin-electron"
const profile: Profile = {
name: 'git',
displayName: 'Git',
description: 'Git plugin',
}
export class GitPlugin extends ElectronBasePlugin {
clients: GitPluginClient[] = []
constructor() {
super(profile, clientProfile, GitPluginClient)
}
}
const clientProfile: Profile = {
name: 'git',
displayName: 'Git',
description: 'Git plugin',
methods: ['log', 'status', 'add', 'commit', 'push', 'pull', 'clone', 'checkout', 'branch', 'merge', 'reset', 'revert', 'diff', 'stash', 'apply', 'cherryPick', 'rebase', 'tag', 'fetch', 'remote', 'config', 'show', 'init', 'help', 'version']
}
// TODO: implement all native OS git commands
class GitPluginClient extends ElectronBasePluginClient {
constructor(webContentsId: number, profile: Profile) {
super(webContentsId, profile)
this.onload(() => {
console.log('GitPluginClient onload')
})
}
}

@ -5,6 +5,7 @@ import fs from 'fs/promises'
import git from 'isomorphic-git' import git from 'isomorphic-git'
import { dialog } from "electron"; import { dialog } from "electron";
import http from 'isomorphic-git/http/web' import http from 'isomorphic-git/http/web'
import { gitProxy } from "../tools/git";
const profile: Profile = { const profile: Profile = {
name: 'isogit', name: 'isogit',
@ -45,11 +46,12 @@ const clientProfile: Profile = {
name: 'isogit', name: 'isogit',
displayName: 'isogit', displayName: 'isogit',
description: 'isogit plugin', description: 'isogit plugin',
methods: ['init', 'localStorageUsed', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'openFolder'] methods: ['init', 'localStorageUsed', 'version', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'openFolder']
} }
class IsoGitPluginClient extends ElectronBasePluginClient { class IsoGitPluginClient extends ElectronBasePluginClient {
workingDir: string = '/Volumes/bunsen/code/empty/' workingDir: string = '/Volumes/bunsen/code/empty/'
gitIsInstalled: boolean = false
constructor(webContentsId: number, profile: Profile) { constructor(webContentsId: number, profile: Profile) {
super(webContentsId, profile) super(webContentsId, profile)
this.onload(() => { this.onload(() => {
@ -57,13 +59,18 @@ class IsoGitPluginClient extends ElectronBasePluginClient {
this.on('fs' as any, 'workingDirChanged', async (path: string) => { this.on('fs' as any, 'workingDirChanged', async (path: string) => {
console.log('workingDirChanged', path) console.log('workingDirChanged', path)
this.workingDir = path this.workingDir = path
await this.status({ this.gitIsInstalled = await gitProxy.version() ? true : false
if (this.gitIsInstalled) {
}) console.log('git is installed')
}
}) })
}) })
} }
async version() {
return gitProxy.version()
}
async getGitConfig() { async getGitConfig() {
return { return {
fs, fs,
@ -72,7 +79,14 @@ class IsoGitPluginClient extends ElectronBasePluginClient {
} }
async status(cmd: any) { async status(cmd: any) {
console.log('status') console.log('status', cmd)
if(this.gitIsInstalled){
const status = await gitProxy.status(this.workingDir)
console.log('STATUS', status)
return status
}
const status = await git.statusMatrix({ const status = await git.statusMatrix({
...await this.getGitConfig(), ...await this.getGitConfig(),
...cmd ...cmd
@ -82,6 +96,15 @@ class IsoGitPluginClient extends ElectronBasePluginClient {
} }
async log(cmd: any) { async log(cmd: any) {
/* we will use isomorphic git for now
if(this.gitIsInstalled){
const log = await gitProxy.log(this.workingDir, cmd.ref)
console.log('LOG', log)
return log
}
*/
console.log('log') console.log('log')
const log = await git.log({ const log = await git.log({
...await this.getGitConfig(), ...await this.getGitConfig(),
@ -214,6 +237,11 @@ class IsoGitPluginClient extends ElectronBasePluginClient {
async clone(cmd: any) { async clone(cmd: any) {
console.log('clone') console.log('clone')
if (this.gitIsInstalled) {
await gitProxy.clone(cmd.url, cmd.dir)
console.log('CLONING WITH NATIVE GIT', cmd)
} else {
try { try {
const clone = await git.clone({ const clone = await git.clone({
...await this.getGitConfig(), ...await this.getGitConfig(),
@ -228,6 +256,7 @@ class IsoGitPluginClient extends ElectronBasePluginClient {
throw e throw e
} }
} }
}
async addremote(cmd: any) { async addremote(cmd: any) {
console.log('addremote') console.log('addremote')

@ -0,0 +1,133 @@
import { exec } from 'child_process';
import { CommitObject, ReadCommitResult } from 'isomorphic-git';
import { promisify } from 'util';
const execAsync = promisify(exec);
const statusTransFormMatrix = (status: string) => {
switch (status) {
case '??':
return [0, 2, 0]
case 'A ':
return [0, 2, 2]
case 'M ':
return [1, 2, 2]
case 'MM':
return [1, 2, 3]
case ' M':
return [1, 2, 1]
case ' D':
return [0, 2, 0]
case 'D ':
return [1, 0, 0]
case 'AM':
return [0, 2, 3]
default:
return [-1, -1, -1]
}
}
export const gitProxy = {
version: async () => {
try {
const result = await execAsync('git --version');
console.log('git --version', result.stdout)
return result.stdout
} catch (error) {
return false;
}
},
clone: async (url: string, path: string) => {
const { stdout, stderr } = await execAsync(`git clone ${url} ${path}`);
console.log('stdout:', stdout);
console.log('stderr:', stderr);
},
status: async (path: string) => {
const result = await execAsync('git status --porcelain -uall', { cwd: path })
//console.log('git status --porcelain -uall', result.stdout)
// parse the result.stdout
const lines = result.stdout.split('\n')
const files: any = []
const fileNames: any = []
//console.log('lines', lines)
lines.forEach((line: string) => {
// get the first two characters of the line
const status = line.slice(0, 2)
const file = line.split(' ').pop()
//console.log('line', line)
if (status && file) {
fileNames.push(file)
files.push([
file,
...statusTransFormMatrix(status)
])
}
}
)
// sort files by first column
files.sort((a: any, b: any) => {
if (a[0] < b[0]) {
return -1
}
if (a[0] > b[0]) {
return 1
}
return 0
})
return files
},
// buggy, doesn't work properly yet on windows
log: async (path: string, ref: string) => {
const result = await execAsync('git log ' + ref + ' --pretty=format:"{ oid:%H, message:"%s", author:"%an", email: "%ae", timestamp:"%at", tree: "%T", committer: "%cn", committer-email: "%ce", committer-timestamp: "%ct", parent: "%P" }" -n 20', { cwd: path })
console.log('git log', result.stdout)
const lines = result.stdout.split('\n')
const commits: ReadCommitResult[] = []
console.log('lines', lines)
lines.forEach((line: string) => {
console.log('line', normalizeJson(line))
line = normalizeJson(line)
const data = JSON.parse(line)
let commit: ReadCommitResult = {} as ReadCommitResult
commit.oid = data.oid
commit.commit = {} as CommitObject
commit.commit.message = data.message
commit.commit.tree = data.tree
commit.commit.committer = {} as any
commit.commit.committer.name = data.committer
commit.commit.committer.email = data['committer-email']
commit.commit.committer.timestamp = data['committer-timestamp']
commit.commit.author = {} as any
commit.commit.author.name = data.author
commit.commit.author.email = data.email
commit.commit.author.timestamp = data.timestamp
commit.commit.parent = [data.parent]
console.log('commit', commit)
commits.push(commit)
})
return commits
}
}
function normalizeJson(str: string){
return str.replace(/[\s\n\r\t]/gs, '').replace(/,([}\]])/gs, '$1')
.replace(/([,{\[]|)(?:("|'|)([\w_\- ]+)\2:|)("|'|)(.*?)\4([,}\]])/gs, (str, start, q1, index, q2, item, end) => {
item = item.replace(/"/gsi, '').trim();
if(index){index = '"'+index.replace(/"/gsi, '').trim()+'"';}
if(!item.match(/^[0-9]+(\.[0-9]+|)$/) && !['true','false'].includes(item)){item = '"'+item+'"';}
if(index){return start+index+':'+item+end;}
return start+item+end;
});
}

@ -120,7 +120,6 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React.
} else await basicWorkspaceInit(workspaces, workspaceProvider) } else await basicWorkspaceInit(workspaces, workspaceProvider)
} else if (isElectron()) { } else if (isElectron()) {
console.log('isElectron initWorkspace') console.log('isElectron initWorkspace')
plugin.call('notification', 'toast', `connecting to electron...`)
if (params.opendir) { if (params.opendir) {
params.opendir = decodeURIComponent(params.opendir) params.opendir = decodeURIComponent(params.opendir)
plugin.call('notification', 'toast', `opening ${params.opendir}...`) plugin.call('notification', 'toast', `opening ${params.opendir}...`)

Loading…
Cancel
Save