git4refactor
filip mertens 9 months ago
parent 88cef7b6bf
commit 82caba939f
  1. 185
      apps/remix-ide/src/app/files/dgitProvider.ts
  2. 8
      libs/remix-ui/git/src/components/navigation/branchedetails.tsx
  3. 5
      libs/remix-ui/git/src/components/panels/commands/fetch.tsx
  4. 4
      libs/remix-ui/git/src/components/panels/commands/pushpull.tsx
  5. 107
      libs/remix-ui/git/src/components/panels/github.tsx
  6. 57
      libs/remix-ui/git/src/components/panels/githubcredentials.tsx
  7. 19
      libs/remix-ui/git/src/components/panels/remotesimport.tsx
  8. 17
      libs/remix-ui/git/src/components/panels/repositories.tsx
  9. 12
      libs/remix-ui/git/src/components/panels/tokenWarning.tsx
  10. 141
      libs/remix-ui/git/src/lib/gitactions.ts
  11. 4
      libs/remix-ui/git/src/lib/listeners.ts
  12. 16
      libs/remix-ui/git/src/state/context.tsx
  13. 7
      libs/remix-ui/git/src/state/gitpayload.ts
  14. 11
      libs/remix-ui/git/src/types/index.ts

@ -14,22 +14,27 @@ 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 { Registry } from '@remix-project/remix-lib'
import { Octokit, App } from "octokit"
import { OctokitResponse } from '@octokit/types'
import { Endpoints } from "@octokit/types"
import { IndexedDBStorage } from './filesystems/indexedDB'
import { GitHubUser, RateLimit, branch, commitChange, remote } from '@remix-ui/git'
import { LibraryProfile, StatusEvents } from '@remixproject/plugin-utils'
import { ITerminal } from '@remixproject/plugin-api/src/lib/terminal'
declare global {
interface Window { remixFileSystemCallback: IndexedDBStorage; remixFileSystem: any; }
}
const profile = {
const profile: LibraryProfile = {
name: 'dGitProvider',
displayName: 'Decentralized git',
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', 'reset', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'version', 'updateSubmodules'
methods: ['init', 'localStorageUsed', 'addremote', 'delremote', 'remotes', 'fetch', 'clone', 'export', 'import', 'status', 'log', 'commit', 'add', 'remove', 'reset', 'rm', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pull', 'setIpfsConfig', 'zip', 'setItem', 'getItem', 'version', 'updateSubmodules'
, 'getGitHubUser', 'remotebranches', 'remotecommits', 'repositories', 'getCommitChanges'],
kind: 'file-system'
}
@ -63,7 +68,7 @@ class DGitProvider extends Plugin {
this.ipfsSources = [this.remixIPFS, this.globalIPFSConfig, this.ipfsconfig]
}
async getGitConfig(dir = '') {
async addIsomorphicGitConfigFS(dir = '') {
if ((Registry.getInstance().get('platform').api.isDesktop())) {
return {
@ -81,14 +86,15 @@ class DGitProvider extends Plugin {
}
}
async parseInput(input) {
async addIsomorphicGitConfig(input) {
const token = await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token')
return {
corsProxy: 'https://corsproxy.remixproject.org/',
http,
onAuth: url => {
url
const auth = {
username: input.token,
username: input.token || token,
password: ''
}
return auth
@ -96,6 +102,33 @@ class DGitProvider extends Plugin {
}
}
async getCommandUser(input) {
const author = {
name: '',
email: ''
}
if (input && input.name && input.email) {
author.name = input.name
author.email = input.email
} else {
const username = await this.call('config' as any, 'getAppParameter', 'settings/github-user-name')
const email = await this.call('config' as any, 'getAppParameter', 'settings/github-email')
const token = await this.call('config' as any, 'getAppParameter', 'settings/gist-access-token')
if (username && email) {
author.name = username
author.email = email
} else if (token) {
console.log('token', token)
const gitHubUser = await this.getGitHubUser({ token })
console.log('gitHubUser', gitHubUser)
if (gitHubUser) {
author.name = gitHubUser.user.login
}
}
}
return author
}
async init(input?) {
if ((Registry.getInstance().get('platform').api.isDesktop())) {
await this.call('isogit', 'init', {
@ -106,7 +139,7 @@ class DGitProvider extends Plugin {
}
await git.init({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
defaultBranch: (input && input.branch) || 'main'
})
this.emit('init')
@ -131,7 +164,7 @@ class DGitProvider extends Plugin {
const status = await git.statusMatrix({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
@ -144,7 +177,7 @@ class DGitProvider extends Plugin {
await this.call('isogit', 'add', cmd)
} else {
await git.add({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
}
@ -158,7 +191,7 @@ class DGitProvider extends Plugin {
await this.call('isogit', 'rm', cmd)
} else {
await git.remove({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
this.emit('rm')
@ -172,7 +205,7 @@ class DGitProvider extends Plugin {
await this.call('isogit', 'reset', cmd)
} else {
await git.resetIndex({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
this.emit('rm')
@ -187,7 +220,7 @@ class DGitProvider extends Plugin {
} else {
const gitmodules = await this.parseGitmodules() || []
await git.checkout({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
const newgitmodules = await this.parseGitmodules() || []
@ -199,12 +232,12 @@ class DGitProvider extends Plugin {
})
for (const module of toRemove) {
const path = (await this.getGitConfig(module.path)).dir
const path = (await this.addIsomorphicGitConfigFS(module.path)).dir
if (await window.remixFileSystem.exists(path)) {
const stat = await window.remixFileSystem.stat(path)
try {
if (stat.isDirectory()) {
await window.remixFileSystem.unlink((await this.getGitConfig(module.path)).dir)
await window.remixFileSystem.unlink((await this.addIsomorphicGitConfigFS(module.path)).dir)
}
} catch (e) {
// do nothing
@ -234,7 +267,7 @@ class DGitProvider extends Plugin {
const status = await git.log({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd,
depth: 10
})
@ -244,7 +277,7 @@ class DGitProvider extends Plugin {
async getCommitChanges(commitHash1, commitHash2): Promise<commitChange[]> {
//console.log([git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })])
const result: commitChange[] = await git.walk({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })],
map: async function (filepath, [A, B]) {
// ignore directories
@ -300,9 +333,9 @@ class DGitProvider extends Plugin {
return await this.call('isogit', 'remotes', config)
}
let remotes = []
let remotes: remote[] = []
try {
remotes = await git.listRemotes({ ...config ? config : await this.getGitConfig() })
remotes = await git.listRemotes({ ...config ? config : await this.addIsomorphicGitConfigFS() })
} catch (e) {
// do nothing
}
@ -316,7 +349,7 @@ class DGitProvider extends Plugin {
status = await this.call('isogit', 'branch', cmd)
} else {
status = await git.branch({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
}
@ -331,14 +364,12 @@ class DGitProvider extends Plugin {
async currentbranch(config) {
if ((Registry.getInstance().get('platform').api.isDesktop())) {
return await this.call('isogit', 'currentbranch')
}
try {
const defaultConfig = await this.getGitConfig()
const defaultConfig = await this.addIsomorphicGitConfigFS()
const cmd = config ? defaultConfig ? { ...defaultConfig, ...config } : config : defaultConfig
const name = await git.currentBranch(cmd)
console.log('current branch', name)
@ -348,8 +379,7 @@ class DGitProvider extends Plugin {
...defaultConfig,
path: `branch.${name}.remote`
})
if (remoteName)
{
if (remoteName) {
const remoteUrl = await git.getConfig({
...defaultConfig,
path: `remote.${remoteName}.url`
@ -377,14 +407,14 @@ class DGitProvider extends Plugin {
}
try {
const defaultConfig = await this.getGitConfig()
const defaultConfig = await this.addIsomorphicGitConfigFS()
const cmd = config ? defaultConfig ? { ...defaultConfig, ...config } : config : defaultConfig
const remotes = await this.remotes(config)
let branches = []
let branches: branch[] = []
branches = (await git.listBranches(cmd)).map((branch) => { return { remote: undefined, name: branch } })
for (const remote of remotes) {
cmd.remote = remote.remote
const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote.remote, name: branch } })
const remotebranches = (await git.listBranches(cmd)).map((branch) => { return { remote: remote, name: branch } })
branches = [...branches, ...remotebranches]
}
return branches
@ -409,7 +439,7 @@ class DGitProvider extends Plugin {
await this.init()
try {
const sha = await git.commit({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
this.emit('commit')
@ -427,7 +457,7 @@ class DGitProvider extends Plugin {
}
const filesInStaging = await git.listFiles({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
return filesInStaging
@ -440,7 +470,7 @@ class DGitProvider extends Plugin {
}
const oid = await git.resolveRef({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
return oid
@ -452,7 +482,7 @@ class DGitProvider extends Plugin {
return readBlobResult
}
const readBlobResult = await git.readBlob({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd
})
@ -481,7 +511,7 @@ class DGitProvider extends Plugin {
await this.call('isogit', 'addremote', { url: input.url, remote: input.remote })
return
}
await git.addRemote({ ...await this.getGitConfig(), url: input.url, remote: input.remote })
await git.addRemote({ ...await this.addIsomorphicGitConfigFS(), url: input.url, remote: input.remote })
}
async delremote(input) {
@ -489,7 +519,7 @@ class DGitProvider extends Plugin {
await this.call('isogit', 'delremote', { remote: input.remote })
return
}
await git.deleteRemote({ ...await this.getGitConfig(), remote: input.remote })
await git.deleteRemote({ ...await this.addIsomorphicGitConfigFS(), remote: input.remote })
}
async localStorageUsed() {
@ -510,11 +540,11 @@ class DGitProvider extends Plugin {
input
}
this.call('terminal', 'logHtml', `Cloning ${input.url}... please wait...`)
try{
try {
const result = await this.call('isogit', 'clone', cmd)
this.call('fs', 'openWindow', folder)
return result
}catch(e){
} catch (e) {
this.call('notification', 'alert', {
id: 'dgitAlert',
message: 'Unexpected error while cloning the repository: \n' + e.toString(),
@ -530,8 +560,8 @@ class DGitProvider extends Plugin {
singleBranch: input.singleBranch,
ref: input.branch,
depth: input.depth || 10,
...await this.parseInput(input),
...await this.getGitConfig()
...await this.addIsomorphicGitConfig(input),
...await this.addIsomorphicGitConfigFS()
}
this.call('terminal', 'logHtml', `Cloning ${input.url}...`)
const result = await git.clone(cmd)
@ -545,12 +575,12 @@ class DGitProvider extends Plugin {
}
}
async parseGitmodules (dir = '') {
async parseGitmodules(dir = '') {
try {
const gitmodules = await this.call('fileManager', 'readFile', path.join(dir, '.gitmodules'))
if (gitmodules) {
const lines = gitmodules.split('\n')
let currentModule:any = {}
let currentModule: any = {}
const modules = []
for (let line of lines) {
line = line.trim()
@ -585,7 +615,7 @@ class DGitProvider extends Plugin {
if (gitmodules) {
for (const module of gitmodules) {
const dir = path.join(currentDir, module.path)
const targetPath = (await this.getGitConfig(dir)).dir
const targetPath = (await this.addIsomorphicGitConfigFS(dir)).dir
if (await window.remixFileSystem.exists(targetPath)) {
const stat = await window.remixFileSystem.stat(targetPath)
try {
@ -600,7 +630,7 @@ class DGitProvider extends Plugin {
for (const module of gitmodules) {
const dir = path.join(currentDir, module.path)
// if url contains git@github.com: convert it
if(module.url && module.url.startsWith('git@github.com:')) {
if (module.url && module.url.startsWith('git@github.com:')) {
module.url = module.url.replace('git@github.com:', 'https://github.com/')
}
try {
@ -608,51 +638,52 @@ class DGitProvider extends Plugin {
url: module.url,
singleBranch: true,
depth: 1,
...await this.parseInput(input),
...await this.getGitConfig(dir)
...await this.addIsomorphicGitConfig(input),
...await this.addIsomorphicGitConfigFS(dir)
}
this.call('terminal', 'logHtml', `Cloning submodule ${dir}...`)
await git.clone(cmd)
this.call('terminal', 'logHtml', `Cloned successfully submodule ${dir}...`)
const commitHash = await git.resolveRef({
...await this.getGitConfig(currentDir),
...await this.addIsomorphicGitConfigFS(currentDir),
ref: 'HEAD'
})
const result = await git.walk({
...await this.getGitConfig(currentDir),
...await this.addIsomorphicGitConfigFS(currentDir),
trees: [git.TREE({ ref: commitHash })],
map: async function (filepath, [A]) {
if(filepath === module.path) {
if (filepath === module.path) {
return await A.oid()
}
}
})
if(result && result.length) {
if (result && result.length) {
this.call('terminal', 'logHtml', `Checking out submodule ${dir} to ${result[0]} in directory ${dir}`)
await git.fetch({
...await this.parseInput(input),
...await this.getGitConfig(dir),
...await this.addIsomorphicGitConfig(input),
...await this.addIsomorphicGitConfigFS(dir),
singleBranch: true,
ref: result[0]
})
await git.checkout({
...await this.getGitConfig(dir),
...await this.addIsomorphicGitConfigFS(dir),
ref: result[0]
})
const log = await git.log({
...await this.getGitConfig(dir),
...await this.addIsomorphicGitConfigFS(dir),
})
if(log[0].oid !== result[0]) {
if (log[0].oid !== result[0]) {
this.call('terminal', 'log', {
type: 'error',
value: `Could not checkout submodule to ${result[0]}`
})} else {
this.call('terminal', 'logHtml',`Checked out submodule ${dir} to ${result[0]}`)
})
} else {
this.call('terminal', 'logHtml', `Checked out submodule ${dir} to ${result[0]}`)
}
}
@ -682,10 +713,7 @@ class DGitProvider extends Plugin {
ref: input.ref,
remoteRef: input.remoteRef,
remote: input.remote,
author: {
name: input.name,
email: input.email
},
author: await this.getCommandUser(input),
input,
}
if ((Registry.getInstance().get('platform').api.isDesktop())) {
@ -694,12 +722,14 @@ class DGitProvider extends Plugin {
const cmd2 = {
...cmd,
...await this.parseInput(input),
...await this.addIsomorphicGitConfig(input),
}
return await git.push({
...await this.getGitConfig(),
const result = await git.push({
...await this.addIsomorphicGitConfigFS(),
...cmd2
})
console.log('push result', result)
return result
}
}
@ -708,10 +738,7 @@ class DGitProvider extends Plugin {
const cmd = {
ref: input.ref,
remoteRef: input.remoteRef,
author: {
name: input.name,
email: input.email
},
author: await this.getCommandUser(input),
remote: input.remote,
input,
}
@ -722,13 +749,14 @@ class DGitProvider extends Plugin {
else {
const cmd2 = {
...cmd,
...await this.parseInput(input),
...await this.addIsomorphicGitConfig(input),
}
result = await git.pull({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd2
})
}
console.log('pull result', result)
setTimeout(async () => {
await this.call('fileManager', 'refresh')
}, 1000)
@ -739,10 +767,7 @@ class DGitProvider extends Plugin {
const cmd = {
ref: input.ref,
remoteRef: input.remoteRef,
author: {
name: input.name,
email: input.email
},
author: await this.getCommandUser(input),
remote: input.remote,
input
}
@ -752,13 +777,19 @@ class DGitProvider extends Plugin {
} else {
const cmd2 = {
...cmd,
...await this.parseInput(input),
...await this.addIsomorphicGitConfig(input),
}
result = await git.fetch({
...await this.getGitConfig(),
...await this.addIsomorphicGitConfigFS(),
...cmd2
})
console.log('fetch result', result)
console.log({
...await this.addIsomorphicGitConfigFS(),
...cmd2
})
}
setTimeout(async () => {
await this.call('fileManager', 'refresh')
}, 1000)
@ -979,7 +1010,7 @@ class DGitProvider extends Plugin {
owner: input.owner,
repo: input.repo,
sha: input.branch,
per_page: input.length
per_page: 100
})
@ -995,11 +1026,11 @@ class DGitProvider extends Plugin {
console.log('octokit', input.token)
const data = await octokit.request('GET /user/repos', {
per_page: 100,
page: 1
per_page: 200,
page: 2
})
console.log(data.data)
console.log(data.data)
return data.data
}

@ -1,4 +1,4 @@
import { faCaretUp, faCaretDown, faCaretRight, faArrowUp, faArrowDown, faArrowRotateRight, faArrowsUpDown, faGlobe, faCheckCircle, faToggleOff, faToggleOn } from "@fortawesome/free-solid-svg-icons";
import { faCaretUp, faCaretDown, faCaretRight, faArrowUp, faArrowDown, faArrowRotateRight, faArrowsUpDown, faGlobe, faCheckCircle, faToggleOff, faToggleOn, faSync } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useContext, useEffect } from "react";
import { branch } from "../../types";
@ -44,8 +44,10 @@ export const BrancheDetailsNavigation = (props: BrancheDetailsNavigationProps) =
:
<FontAwesomeIcon className='ml-auto mr-1 pointer' icon={faToggleOn} onClick={() => checkout(branch)}></FontAwesomeIcon>
}
<FontAwesomeIcon className='ml-auto pointer' icon={faArrowsUpDown} onClick={() => checkout(branch)}></FontAwesomeIcon>
{branch.remote?.url && <FontAwesomeIcon className='ml-2 pointer' icon={faGlobe} onClick={() => openRemote()}></FontAwesomeIcon>}
{branch.remote?.url && <>
<FontAwesomeIcon className='ml-auto pointer' icon={faSync} onClick={() => checkout(branch)}></FontAwesomeIcon>
<FontAwesomeIcon className='ml-2 pointer' icon={faGlobe} onClick={() => openRemote()}></FontAwesomeIcon></>}
</div>
</>
);

@ -1,10 +1,11 @@
import React, { useEffect, useState } from "react";
import { gitActionsContext } from "../../../state/context";
export const Fetch = () => {
const actions = React.useContext(gitActionsContext)
const fetch = async () => {
//gitservice.fetch(currentRemote, '', '')
await actions.fetch()
}

@ -50,11 +50,11 @@ export const PushPull = () => {
}
const push = async () => {
//gitservice.push(currentRemote, branch || '', remoteBranch, force)
actions.push()
}
const pull = async () => {
//gitservice.pull(currentRemote, branch || '', remoteBranch)
actions.pull()
}

@ -1,6 +1,6 @@
import React, { useEffect } from "react";
import { gitActionsContext, pluginActionsContext } from "../../state/context";
import { gitPluginContext } from "../gitui";
import { gitPluginContext, loaderContext } from "../gitui";
import axios from "axios";
import { CopyToClipboard } from "@remix-ui/clipboard";
import { Card } from "react-bootstrap";
@ -9,80 +9,20 @@ import { Card } from "react-bootstrap";
export const GitHubAuth = () => {
const context = React.useContext(gitPluginContext)
const actions = React.useContext(gitActionsContext)
const loader = React.useContext(loaderContext)
const pluginActions = React.useContext(pluginActionsContext)
const [gitHubResponse, setGitHubResponse] = React.useState<any>(null)
const [authorized, setAuthorized] = React.useState<boolean>(false)
const client_id = 'Iv1.12fc02c69c512462'// 'e90cf20e6cafa2fd71ea'
const getDeviceCodeFromGitHub = async () => {
setAuthorized(false)
// Send a POST request
const response = await axios({
method: 'post',
url: 'http://0.0.0.0:3000/github.com/login/device/code',
data: {
client_id // : 'Iv1.12fc02c69c512462'
},
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
});
// convert response to json
const githubrespone = await response.data;
console.log('json', githubrespone)
setGitHubResponse(githubrespone)
}
const connectApp = async () => {
// poll https://github.com/login/oauth/access_token
const accestokenresponse = await axios({
method: 'post',
url: 'http://0.0.0.0:3000/github.com/login/oauth/access_token',
data: {
client_id,// : 'Iv1.12fc02c69c512462',
device_code: gitHubResponse.device_code,
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
},
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
});
// convert response to json
const response = await accestokenresponse.data;
console.log('json2', response)
if (response.error) {
}
if (response.access_token) {
setAuthorized(true)
await pluginActions.saveToken(response.access_token)
await actions.getGitHubUser()
}
}
const disconnect = async () => {
setAuthorized(false)
setGitHubResponse(null)
}
useEffect(() => {
checkConnection()
}, [context.gitHubAccessToken, loader.plugin])
const checkConnection = async () => {
//await actions.getGitHubUser()
console.log('checkConnection', context.gitHubAccessToken)
await actions.getGitHubUser()
}
useEffect(() => {
},[])
useEffect(() => {
console.log('context.rateLimit', context.rateLimit)
}, [context.rateLimit])
@ -91,37 +31,8 @@ export const GitHubAuth = () => {
return (
<>
{(context.gitHubUser && context.gitHubUser.login) ? null :
<button className='btn btn-primary mt-1 w-100' onClick={async () => {
getDeviceCodeFromGitHub();
}}>Sign in with GitHub</button>
}
{gitHubResponse && !authorized &&
<div className="pt-2">
Step 1: Copy this code:
<div className="input-group text-secondary mb-0 h6">
<input disabled type="text" className="form-control" value={gitHubResponse.user_code} />
<div className="input-group-append">
<CopyToClipboard content={gitHubResponse.user_code} data-id='copyToClipboardCopyIcon' className='far fa-copy ml-1 p-2 mt-1' direction={"top"} />
</div>
</div>
<br></br>
Step 2: Authorize the app here
<br></br><a target="_blank" href={gitHubResponse.verification_uri}>{gitHubResponse.verification_uri}</a>
<br /><br></br>
Step 3: When you are done, click on the button below:
<button className='btn btn-primary mt-1 w-100' onClick={async () => {
connectApp()
}}>Connect</button>
</div>
}
{
(context.gitHubUser && context.gitHubUser.login) ?
<div className="pt-2">
<button className='btn btn-primary mt-1 w-100' onClick={async () => {
disconnect()
}}>Sign out</button>
</div>: null
<li className="text-warning list-group-item d-flex justify-content-between align-items-center">
Not connected to GitHub. Add a valid token.</li>
}
{
(context.gitHubUser && context.gitHubUser.login) ?

@ -1,7 +1,7 @@
import { checkout, clone, ReadCommitResult } from "isomorphic-git";
import React from "react";
import { gitActionsContext } from "../../state/context";
import { gitPluginContext } from "../gitui";
import React, { useEffect } from "react";
import { gitActionsContext, pluginActionsContext } from "../../state/context";
import { gitPluginContext, loaderContext } from "../gitui";
import { CustomTooltip } from "@remix-ui/helper";
import { useIntl, FormattedMessage } from "react-intl";
@ -11,46 +11,75 @@ import { FormControl, InputGroup } from "react-bootstrap";
export const GitHubCredentials = () => {
const context = React.useContext(gitPluginContext)
const pluginactions = React.useContext(pluginActionsContext)
const loader = React.useContext(loaderContext)
const [githubToken, setGithubToken] = React.useState('')
const [githubUsername, setGithubUsername] = React.useState('')
const [githubEmail, setGithubEmail] = React.useState('')
const intl = useIntl()
const gitAccessTokenLink = 'https://github.com/settings/tokens/new?scopes=gist,repo&description=Remix%20IDE%20Token'
useEffect(() => {
refresh()
}, [loader.plugin, context.gitHubAccessToken])
function handleChangeTokenState(e: string): void {
throw new Error("Function not implemented.");
setGithubToken(e)
}
function handleChangeUserNameState(e: string): void {
throw new Error("Function not implemented.");
setGithubUsername(e)
}
function handleChangeEmailState(e: string): void {
throw new Error("Function not implemented.");
setGithubEmail(e)
}
function saveGithubToken(): void {
throw new Error("Function not implemented.");
async function saveGithubToken() {
await pluginactions.saveGitHubCredentials({
username: githubUsername,
email: githubEmail,
token: githubToken
})
}
async function refresh() {
const credentials = await pluginactions.getGitHubCredentials()
if(!credentials) return
console.log('credentials', credentials)
setGithubToken(credentials.token || '')
setGithubUsername(credentials.username || '')
setGithubEmail(credentials.email || '')
}
function removeToken(): void {
throw new Error("Function not implemented.");
setGithubToken('')
setGithubUsername('')
setGithubEmail('')
pluginactions.saveGitHubCredentials({
username: '',
email: '',
token: ''
})
}
return (
<>
<hr></hr>
<label className="pr-1">Manual Configuration</label>
<div className="input-group text-secondary mb-1 h6">
<input type="text" placeholder="GitHub token" className="form-control" name='githubToken' />
<input type="password" value={githubToken} placeholder="GitHub token" className="form-control" name='githubToken' onChange={e => handleChangeTokenState(e.target.value)} />
<div className="input-group-append">
<CopyToClipboard content={''} data-id='copyToClipboardCopyIcon' className='far fa-copy ml-1 p-2 mt-1' direction={"top"} />
<CopyToClipboard content={githubToken} data-id='copyToClipboardCopyIcon' className='far fa-copy ml-1 p-2 mt-1' direction={"top"} />
</div>
</div>
<input name='githubUsername' onChange={e => handleChangeUserNameState(e.target.value)} value={githubUsername} className="form-control mb-1" placeholder="GitHub username" type="text" id="githubUsername" />
<input name='githubEmail' onChange={e => handleChangeEmailState(e.target.value)} value={githubEmail} className="form-control mb-1" placeholder="GitHub email" type="text" id="githubEmail" />
<div className="d-flex justify-content-between">
<button className="btn btn-primary w-100" onClick={saveGithubToken}>
<FormattedMessage id="save" defaultMessage="Save" />
</button>
<button className="btn btn-danger far fa-trash-alt" onClick={removeToken}>
</button>
</div>
<hr />
</>
);

@ -5,6 +5,7 @@ import { repository } from "../../types";
import { gitPluginContext } from "../gitui";
import Select from 'react-select'
import { selectStyles, selectTheme } from "../../types/styles";
import { TokenWarning } from "./tokenWarning";
export const RemotesImport = () => {
@ -18,17 +19,20 @@ export const RemotesImport = () => {
useEffect(() => {
console.log('context', context.repositories)
// map context.repositories to options
const options = context.repositories && context.repositories.length > 0 && context.repositories.map(repo => {
return { value: repo.id, label: repo.full_name }
})
if (context.repositories && context.repositories.length > 0) {
// map context.repositories to options
const options = context.repositories && context.repositories.length > 0 && context.repositories.map(repo => {
return { value: repo.id, label: repo.full_name }
})
setRepoOptions(options)
} else {
setRepoOptions(null)
setShow(false)
}
setLoading(false)
setRepoOptions(options)
}, [context.repositories])
const fetchRepositories = async () => {
try {
setShow(true)
@ -67,6 +71,7 @@ export const RemotesImport = () => {
return (
<>
<TokenWarning />
<Button onClick={fetchRepositories} className="w-100 mt-1">
<i className="fab fa-github mr-1"></i>Fetch Remotes from GitHub
</Button>

@ -5,6 +5,7 @@ import { repository } from "../../types";
import { gitPluginContext } from "../gitui";
import Select from 'react-select'
import { selectStyles, selectTheme } from "../../types/styles";
import { TokenWarning } from "./tokenWarning";
interface RepositoriesProps {
cloneDepth?: number
@ -24,12 +25,17 @@ export const Repositories = (props: RepositoriesProps) => {
useEffect(() => {
console.log('context', context.repositories)
// map context.repositories to options
const options = context.repositories && context.repositories.length > 0 && context.repositories.map(repo => {
return { value: repo.id, label: repo.full_name }
})
if (context.repositories && context.repositories.length > 0) {
// map context.repositories to options
const options = context.repositories && context.repositories.length > 0 && context.repositories.map(repo => {
return { value: repo.id, label: repo.full_name }
})
setRepoOptions(options)
} else {
setRepoOptions(null)
setShow(false)
}
setLoading(false)
setRepoOptions(options)
}, [context.repositories])
@ -93,6 +99,7 @@ export const Repositories = (props: RepositoriesProps) => {
return (
<>
<TokenWarning/>
<Button onClick={fetchRepositories} className="w-100 mt-1">
<i className="fab fa-github mr-1"></i>Fetch Repositories from GitHub
</Button>

@ -0,0 +1,12 @@
import { gitPluginContext } from "../gitui"
import React, { useEffect, useState } from "react";
export const TokenWarning = () => {
const context = React.useContext(gitPluginContext)
return (<>
{(context.gitHubUser && context.gitHubUser.login) ? null :
<li className="text-warning list-group-item d-flex justify-content-between align-items-center">
To use add a GitHub token to the settings.</li>
}
</>
)
}

@ -2,13 +2,17 @@ import { ViewPlugin } from "@remixproject/engine-web";
import { ReadBlobResult, ReadCommitResult } from "isomorphic-git";
import React from "react";
import { fileStatus, fileStatusMerge, setBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRateLimit, setRemoteBranches, setRemotes, setRepos, setUpstream } from "../state/gitpayload";
import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType } from '../types';
import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType, gitState } from '../types';
import { removeSlash } from "../utils";
import { disableCallBacks, enableCallBacks } from "./listeners";
import { AlertModal, ModalTypes } from "@remix-ui/app";
import { gitActionsContext } from "../state/context";
import { gitPluginContext } from "../components/gitui";
import { setFileDecorators } from "./pluginActions";
import { IDgitSystem, IRemixApi, RemixApi } from "@remixproject/plugin-api";
import { Plugin } from "@remixproject/engine";
import { AnyMxRecord } from "dns";
import { StatusEvents } from "@remixproject/plugin-utils";
export const fileStatuses = [
["new,untracked", 0, 2, 0], // new, untracked
@ -32,13 +36,48 @@ const statusmatrix: statusMatrixType[] = fileStatuses.map((x: any) => {
status: x,
};
});
/*
interface customDGitSystem extends IDgitSystem{
events: StatusEvents,
methods: {
getCommitChanges(oid1: string, oid2: string): Promise<commitChange[]>
getBranchCommits(branch: branch): Promise<ReadCommitResult[]>
fetchBranch(branch: branch): Promise<any>
remotebranches(owner: string, repo: string): Promise<branch[]>
remoteCommits(url: string, branch: string, length: number): Promise<ReadCommitResult[]>
repositories(token: string): Promise<any>
clone(url: string, branch: string, depth: number, singleBranch: boolean): Promise<any>
getGitHubUser(token: string): Promise<{ user: GitHubUser, ratelimit: RateLimit }>
saveGitHubCredentials(credentials: { username: string, email: string, token: string }): Promise<any>
getGitHubCredentials(): Promise<{ username: string, email: string, token: string }>
currentbranch(): Promise<branch>
}
}
let plugin: ViewPlugin, dispatch: React.Dispatch<gitActionDispatch>
interface notificationSystem {
methods: {
toast(message: string): void
alert(message: {
title: string,
type: string
}): void
modal(modal: AlertModal): void
},
events: StatusEvents
}
interface customApi extends IRemixApi {
dGitProvider: customDGitSystem
notification: notificationSystem
}
*/
export const setPlugin = (p: ViewPlugin, dispatcher: React.Dispatch<gitActionDispatch>) => {
let plugin: Plugin, dispatch: React.Dispatch<gitActionDispatch>
export const setPlugin = (p: Plugin, dispatcher: React.Dispatch<gitActionDispatch>) => {
plugin = p
dispatch = dispatcher
console.log('setPlugin')
}
export const getBranches = async () => {
@ -101,7 +140,6 @@ export const gitlog = async () => {
}
dispatch(setCommits(commits))
await showCurrentBranch()
await getGitHubUser()
}
export const showCurrentBranch = async () => {
@ -133,7 +171,13 @@ export const currentBranch = async () => {
// eslint-disable-next-line no-useless-catch
try {
const branch: branch =
(await plugin.call("dGitProvider", "currentbranch")) || "";
(await plugin.call("dGitProvider", "currentbranch")) || {
name: "",
remote: {
remote: "",
url: "",
},
};
return branch;
} catch (e) {
throw e;
@ -329,15 +373,36 @@ export const clone = async (url: string, branch: string, depth: number, singleBr
dispatch(setLoading(false))
}
export const fetch = async(remote?: string, ref?: string, remoteRef?: string) => {
try {
await plugin.call('dGitProvider' as any, 'fetch', { remote, ref, remoteRef })
await gitlog()
await getBranches()
} catch (e: any) {
await parseError(e)
}
}
export const pull = async(remote?: string, ref?: string, remoteRef?: string) => {
try {
await plugin.call('dGitProvider' as any, 'pull', { remote, ref, remoteRef })
await gitlog()
} catch (e: any) {
await parseError(e)
}
}
export const push = async(remote?: string, ref?: string, remoteRef?: string, force?: boolean) => {
try {
await plugin.call('dGitProvider' as any, 'push', { remote, ref, remoteRef, force })
} catch (e: any) {
await parseError(e)
}
}
const tokenWarning = async () => {
const token = await plugin.call('config' as any, 'getAppParameter', 'settings/gist-access-token')
if (!token) {
const modalContent: AlertModal = {
message: 'Please set a token first in the GitHub settings of REMIX',
title: 'No GitHub token set',
id: 'no-token-set',
}
//plugin.call('notification', 'alert', modalContent)
return false;
} else {
return token;
@ -384,15 +449,18 @@ const parseError = async (e: any) => {
}
}
export const repositories = async () => {
try {
const token = await tokenWarning();
if (token) {
const repos = await plugin.call('dGitProvider' as any, 'repositories', { token });
dispatch(setRepos(repos))
} else {
plugin.call('notification', 'alert', {
title: 'Error getting repositories',
message: `Please check your GitHub token in the GitHub settings. It needs to have access to the repositories.`
})
dispatch(setRepos([]))
}
} catch (e) {
console.log(e)
@ -400,6 +468,7 @@ export const repositories = async () => {
title: 'Error getting repositories',
message: `${e.message}: Please check your GitHub token in the GitHub settings.`
})
dispatch(setRepos([]))
}
}
@ -409,6 +478,12 @@ export const remoteBranches = async (owner: string, repo: string) => {
if (token) {
const branches = await plugin.call('dGitProvider' as any, 'remotebranches', { token, owner, repo });
dispatch(setRemoteBranches(branches))
} else {
plugin.call('notification', 'alert', {
title: 'Error getting branches',
message: `Please check your GitHub token in the GitHub settings. It needs to have access to the branches.`
})
dispatch(setRemoteBranches([]))
}
} catch (e) {
console.log(e)
@ -416,6 +491,7 @@ export const remoteBranches = async (owner: string, repo: string) => {
title: 'Error',
message: e.message
})
dispatch(setRemoteBranches([]))
}
}
@ -424,7 +500,7 @@ export const remoteCommits = async (url: string, branch: string, length: number)
console.log(urlParts, 'urlParts')
// check if it's github
if(!urlParts[urlParts.length - 3].includes('github')) {
if (!urlParts[urlParts.length - 3].includes('github')) {
return
}
@ -437,6 +513,11 @@ export const remoteCommits = async (url: string, branch: string, length: number)
console.log(token, owner, repo, branch, length)
const commits = await plugin.call('dGitProvider' as any, 'remotecommits', { token, owner, repo, branch, length });
console.log(commits, 'remote commits')
} else {
plugin.call('notification', 'alert', {
title: 'Error getting commits',
message: `Please check your GitHub token in the GitHub settings. It needs to have access to the commits.`
})
}
} catch (e) {
console.log(e)
@ -447,7 +528,34 @@ export const remoteCommits = async (url: string, branch: string, length: number)
}
}
export const saveGitHubCredentials = async (credentials: { username: string, email: string, token: string }) => {
try {
await plugin.call('config' as any, 'setAppParameter', 'settings/github-user-name', credentials.username)
await plugin.call('config' as any, 'setAppParameter', 'settings/github-email', credentials.email)
await plugin.call('config' as any, 'setAppParameter', 'settings/gist-access-token', credentials.token)
} catch (e) {
console.log(e)
}
}
export const getGitHubCredentials = async () => {
if (!plugin) return
try {
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')
return {
username,
email,
token
}
} catch (e) {
console.log(e)
}
}
export const getGitHubUser = async () => {
if (!plugin) return
try {
const token = await tokenWarning();
if (token) {
@ -460,6 +568,8 @@ export const getGitHubUser = async () => {
dispatch(setGitHubUser(data.user))
dispatch(setRateLimit(data.ratelimit))
} else {
dispatch(setGitHubUser(null))
}
} catch (e) {
console.log(e)
@ -611,6 +721,7 @@ export const getBranchCommits = async (branch: branch) => {
})
console.log(commits)
dispatch(setBranchCommits({ branch, commits }))
await fetchBranch(branch)
return commits
} catch (e) {
console.log(e)

@ -1,7 +1,7 @@
import { ViewPlugin } from "@remixproject/engine-web";
import React from "react";
import { setCanUseApp, setLoading, setRepoName } from "../state/gitpayload";
import { setCanUseApp, setLoading, setRepoName, setGItHubToken } from "../state/gitpayload";
import { gitActionDispatch } from "../types";
import { diffFiles, getBranches, getFileStatusMatrix, getGitHubUser, getRemotes, gitlog, setPlugin } from "./gitactions";
@ -102,7 +102,7 @@ export const getGitConfig = async () => {
const email = await plugin.call('settings', 'get', 'settings/github-email')
const token = await plugin.call('settings', 'get', 'settings/gist-access-token')
const config = { username, email, token }
//dispatch(setGitConfig(config))
gitDispatch(setGItHubToken(config.token))
return config
}

@ -8,9 +8,9 @@ export interface gitActions {
rm(path: string): Promise<void>
commit(message: string): Promise<any>
addall(): Promise<void>
//push(): Promise<void>
//pull(): Promise<void>
//fetch(): Promise<void>
push(remote?: string, ref?: string, remoteRef?: string, force?: boolean): Promise<void>
pull(remote?: string, ref?: string, remoteRef?: string): Promise<void>
fetch(remote?: string, ref?: string, remoteRef?: string): Promise<void>
repositories(): Promise<any>
checkoutfile(file: string): Promise<void>
checkout(cmd: any): Promise<void>
@ -34,6 +34,16 @@ export interface pluginActions {
openFile(path: string): Promise<void>
openDiff(change: commitChange): Promise<void>
saveToken(token: string): Promise<void>
saveGitHubCredentials({
username,
email,
token
}): Promise<void>
getGitHubCredentials(): Promise<{
username: string
email: string
token: string
}>
}
export const pluginActionsContext = React.createContext<pluginActions>(null)

@ -128,3 +128,10 @@ export const setBranchCommits =({branch, commits}) => {
payload: { branch, commits }
}
}
export const setGItHubToken = (token: string) => {
return {
type: 'SET_GITHUB_ACCESS_TOKEN',
payload: token
}
}

@ -39,6 +39,7 @@ export type loaderState = {
remotes: boolean
commits: boolean
sourcecontrol: boolean
plugin: boolean
}
export type commitChangeTypes = {
@ -125,7 +126,8 @@ export const defaultLoaderState: loaderState = {
branches: false,
commits: false,
sourcecontrol: false,
remotes: false
remotes: false,
plugin: false
}
export type fileStatusResult = {
@ -211,4 +213,9 @@ export interface setBranchCommitsAction {
}
}
export type gitActionDispatch = setUpstreamAction | setBranchCommitsAction | setRemotesAction | setCurrentBranchAction | fileStatusAction | setLoadingAction | setCanUseAppAction | setRepoNameAction | setCommitsAction | setBranchesAction | setReposAction | setRemoteBranchesAction
export interface setTokenAction {
type: string,
payload: string
}
export type gitActionDispatch = setTokenAction | setUpstreamAction | setBranchCommitsAction | setRemotesAction | setCurrentBranchAction | fileStatusAction | setLoadingAction | setCanUseAppAction | setRepoNameAction | setCommitsAction | setBranchesAction | setReposAction | setRemoteBranchesAction
Loading…
Cancel
Save