Merge branch 'master' of https://github.com/ethereum/remix-project into editorcontext

editorcontextDummy
filip mertens 2 years ago
commit 372f434f33
  1. 4
      apps/remix-ide-e2e/src/tests/recorder.test.ts
  2. 2
      apps/remix-ide/src/app/components/hidden-panel.tsx
  3. 2
      apps/remix-ide/src/app/components/main-panel.tsx
  4. 2
      apps/remix-ide/src/app/components/side-panel.tsx
  5. 2
      apps/remix-ide/src/app/components/vertical-icons.tsx
  6. 2
      apps/remix-ide/src/app/files/dgitProvider.js
  7. 5
      apps/remix-ide/src/app/panels/file-panel.js
  8. 2
      apps/remix-ide/src/app/panels/terminal.js
  9. 2
      apps/remix-ide/src/app/plugins/permission-handler-plugin.tsx
  10. 3
      apps/remix-ide/src/app/tabs/analysis-tab.js
  11. 2
      apps/remix-ide/src/app/tabs/compile-and-run.ts
  12. 1
      apps/remix-ide/src/app/tabs/compile-tab.js
  13. 3
      apps/remix-ide/src/app/tabs/debugger-tab.js
  14. 2
      apps/remix-ide/src/app/tabs/external-http-provider.tsx
  15. 2
      apps/remix-ide/src/app/tabs/foundry-provider.tsx
  16. 2
      apps/remix-ide/src/app/tabs/ganache-provider.tsx
  17. 13
      apps/remix-ide/src/app/tabs/runTab/model/recorder.js
  18. 5
      apps/remix-ide/src/app/tabs/search.tsx
  19. 5
      apps/remix-ide/src/app/tabs/test-tab.js
  20. 3
      apps/remix-ide/src/app/udapp/run-tab.js
  21. 2
      apps/remix-ide/src/app/ui/landing-page/landing-page.js
  22. 8
      apps/remix-ide/src/blockchain/blockchain.js
  23. 3
      apps/remix-ide/src/remixAppManager.js
  24. 2
      apps/remix-ide/src/walkthroughService.js
  25. 12
      libs/remix-ui/helper/src/lib/helper-components.tsx
  26. 8
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  27. 6
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  28. 26
      libs/remix-ui/run-tab/src/lib/components/recorderCardUI.tsx
  29. 6
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  30. 1
      libs/remix-ui/run-tab/src/lib/types/index.ts
  31. 30
      libs/remix-ui/workspace/src/lib/actions/workspace.ts

@ -118,7 +118,7 @@ module.exports = {
})
.clickFunction('retrieve - call')
.perform((done) => {
browser.verifyCallReturnValue(addressRef, ['', '0:uint256: 350'])
browser.verifyCallReturnValue(addressRef, ['0:uint256: 350'])
.perform(() => done())
})
// change the init state and recompile the same contract.
@ -138,7 +138,7 @@ module.exports = {
})
.clickFunction('retrieve - call')
.perform((done) => {
browser.verifyCallReturnValue(addressRef, ['', '0:uint256: 300'])
browser.verifyCallReturnValue(addressRef, ['0:uint256: 300'])
.perform(() => done())
})
.end()

@ -8,7 +8,7 @@ import { PluginViewWrapper } from '@remix-ui/helper'
const profile = {
name: 'hiddenPanel',
displayName: 'Hidden Panel',
description: '',
description: 'Remix IDE hidden panel',
version: packageJson.version,
methods: ['addView', 'removeView']
}

@ -7,7 +7,7 @@ import { PluginViewWrapper } from '@remix-ui/helper'
const profile = {
name: 'mainPanel',
displayName: 'Main Panel',
description: '',
description: 'Remix IDE main panel',
version: packageJson.version,
methods: ['addView', 'removeView', 'showContent']
}

@ -10,7 +10,7 @@ import { PluginViewWrapper } from '@remix-ui/helper'
const sidePanel = {
name: 'sidePanel',
displayName: 'Side Panel',
description: '',
description: 'Remix IDE side panel',
version: packageJson.version,
methods: ['addView', 'removeView']
}

@ -10,7 +10,7 @@ import { PluginViewWrapper } from '@remix-ui/helper'
const profile = {
name: 'menuicons',
displayName: 'Vertical Icons',
description: '',
description: 'Remix IDE vertical icons',
version: packageJson.version,
methods: ['select', 'unlinkContent', 'linkContent'],
events: ['toggleContent', 'showContent']

@ -18,7 +18,7 @@ const axios = require('axios')
const profile = {
name: 'dGitProvider',
displayName: 'Decentralized git',
description: '',
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', 'lsfiles', 'readblob', 'resolveref', 'branches', 'branch', 'checkout', 'currentbranch', 'push', 'pin', 'pull', 'pinList', 'unPin', 'setIpfsConfig', 'zip', 'setItem', 'getItem'],

@ -33,11 +33,12 @@ const profile = {
methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'setWorkspace', 'registerContextMenuItem', 'renameWorkspace', 'deleteWorkspace'],
events: ['setWorkspace', 'workspaceRenamed', 'workspaceDeleted', 'workspaceCreated'],
icon: 'assets/img/fileManager.webp',
description: ' - ',
description: 'Remix IDE file explorer',
kind: 'fileexplorer',
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/file_explorer.html',
version: packageJson.version
version: packageJson.version,
maintainedBy: 'Remix'
}
module.exports = class Filepanel extends ViewPlugin {
constructor (appManager) {

@ -20,7 +20,7 @@ const profile = {
name: 'terminal',
methods: ['log', 'logHtml'],
events: [],
description: ' - ',
description: 'Remix IDE terminal',
version: packageJson.version
}

@ -7,7 +7,7 @@ import { Profile } from '@remixproject/plugin-utils'
const profile = {
name: 'permissionhandler',
displayName: 'permissionhandler',
description: 'permissionhandler',
description: 'Plugin to handle permissions',
methods: ['askPermission']
}

@ -18,7 +18,8 @@ const profile = {
kind: 'analysis',
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/static_analysis.html',
version: packageJson.version
version: packageJson.version,
maintainedBy: 'Remix'
}
class AnalysisTab extends ViewPlugin {

@ -10,7 +10,7 @@ const _paq = window._paq = window._paq || []
export const profile = {
name: 'compileAndRun',
displayName: 'Compile and Run',
description: 'after each compilation, run the script defined in Natspec.',
description: 'After each compilation, run the script defined in Natspec.',
methods: ['runScriptAfterCompilation'],
version: packageJson.version,
kind: 'none'

@ -19,6 +19,7 @@ const profile = {
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/solidity_editor.html',
version: packageJson.version,
maintainedBy: 'Remix',
methods: ['getCompilationResult', 'compile', 'compileWithParameters', 'setCompilerConfig', 'compileFile', 'getCompilerState']
}

@ -17,7 +17,8 @@ const profile = {
kind: 'debugging',
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/debugger.html',
version: packageJson.version
version: packageJson.version,
maintainedBy: 'Remix'
}
export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {

@ -6,7 +6,7 @@ const profile = {
name: 'basic-http-provider',
displayName: 'External Http Provider',
kind: 'provider',
description: '',
description: 'External Http Provider',
methods: ['sendAsync'],
version: packageJson.version
}

@ -10,7 +10,7 @@ const profile = {
name: 'foundry-provider',
displayName: 'Foundry Provider',
kind: 'provider',
description: 'Anvil',
description: 'Foundry Anvil provider',
methods: ['sendAsync'],
version: packageJson.version
}

@ -10,7 +10,7 @@ const profile = {
name: 'ganache-provider',
displayName: 'Ganache Provider',
kind: 'provider',
description: 'Ganache',
description: 'Truffle Ganache provider',
methods: ['sendAsync'],
version: packageJson.version
}

@ -13,7 +13,7 @@ const _paq = window._paq = window._paq || [] //eslint-disable-line
const profile = {
name: 'recorder',
displayName: 'Recorder',
description: '',
description: 'Records transactions to save and run',
version: packageJson.version,
methods: [ ]
}
@ -200,13 +200,16 @@ class Recorder extends Plugin {
*/
run (records, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, liveMode, newContractFn) {
this.setListen(false)
const liveMsg = liveMode ? ' in live mode' : ''
const liveMsg = liveMode ? ' with updated contracts' : ''
logCallBack(`Running ${records.length} transaction(s)${liveMsg} ...`)
async.eachOfSeries(records, async (tx, index, cb) => {
if (liveMode && tx.record.type === 'constructor') {
// resolve the bytecode using the contract name, this ensure getting the last compiled one.
// resolve the bytecode and ABI using the contract name, this ensure getting the last compiled one.
const data = await this.call('compilerArtefacts', 'getArtefactsByContractName', tx.record.contractName)
tx.record.bytecode = data.artefact.evm.bytecode.object
const updatedABIKeccak = ethutil.bufferToHex(ethutil.keccakFromString(JSON.stringify(data.artefact.abi)))
abis[updatedABIKeccak] = data.artefact.abi
tx.record.abi = updatedABIKeccak
}
var record = this.resolveAddress(tx.record, accounts, options)
var abi = abis[tx.record.abi]
@ -312,11 +315,11 @@ class Recorder extends Plugin {
abis = json.abis || {}
linkReferences = json.linkReferences || {}
} catch (e) {
return cb('Invalid Scenario File. Please try again')
return cb('Invalid scenario file. Please try again')
}
if (!txArray.length) {
return
return cb('No transactions found in scenario file')
}
this.run(txArray, accounts, options, abis, linkReferences, confirmationCb, continueCb, promptCb, alertCb, logCallBack, liveMode, (abi, address, contractName) => {

@ -8,11 +8,12 @@ const profile = {
methods: [''],
events: [],
icon: 'assets/img/search_icon.webp',
description: '',
description: 'Find and replace in file explorer',
kind: '',
location: 'sidePanel',
documentation: '',
version: packageJson.version
version: packageJson.version,
maintainedBy: 'Remix'
}
export class SearchPlugin extends ViewPlugin {

@ -16,9 +16,10 @@ const profile = {
methods: ['testFromPath', 'testFromSource', 'setTestFolderPath', 'getTestlibs', 'createTestLibs'],
events: [],
icon: 'assets/img/unitTesting.webp',
description: 'Fast tool to generate unit tests for your contracts',
description: 'Write and run unit tests for your contracts in Solidity',
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/unittesting.html'
documentation: 'https://remix-ide.readthedocs.io/en/latest/unittesting.html',
maintainedBy: 'Remix'
}
module.exports = class TestTab extends ViewPlugin {

@ -12,11 +12,12 @@ const profile = {
name: 'udapp',
displayName: 'Deploy & run transactions',
icon: 'assets/img/deployAndRun.webp',
description: 'execute and save transactions',
description: 'Execute, save and replay transactions',
kind: 'udapp',
location: 'sidePanel',
documentation: 'https://remix-ide.readthedocs.io/en/latest/run.html',
version: packageJson.version,
maintainedBy: 'Remix',
permission: true,
events: ['newTransaction'],
methods: ['createVMAccount', 'sendTransaction', 'getAccounts', 'pendingTransactionsCount', 'getSettings', 'setEnvironmentMode', 'clearAllInstances', 'addInstance', 'resolveContractAndAddInstance']

@ -9,7 +9,7 @@ const profile = {
displayName: 'Home',
methods: [],
events: [],
description: ' - ',
description: 'Remix home tab ',
icon: 'assets/img/remixLogo.webp',
location: 'mainPanel',
version: packageJson.version

@ -141,9 +141,9 @@ export class Blockchain extends Plugin {
async deployProxy (proxyData, implementationContractObject) {
const proxyModal = {
id: 'confirmProxyDeployment',
title: 'ERC1967',
title: 'Confirm Deploy Proxy (ERC1967)',
message: `Confirm you want to deploy an ERC1967 proxy contract that is connected to your implementation.
For more info on ERC1967, see https://docs.openzeppelin.com/contracts/4.x/api/proxy#ERC1967Proxy`,
For more info on ERC1967, see: https://docs.openzeppelin.com/contracts/4.x/api/proxy#ERC1967Proxy`,
modalType: 'modal',
okLabel: 'OK',
cancelLabel: 'Cancel',
@ -189,8 +189,8 @@ export class Blockchain extends Plugin {
async upgradeProxy(proxyAddress, newImplAddress, data, newImplementationContractObject) {
const upgradeModal = {
id: 'confirmProxyDeployment',
title: 'ERC1967',
message: `Confirm you want to upgrade your contract to new implementation ${newImplAddress}.`,
title: 'Confirm Update Proxy (ERC1967)',
message: `Confirm you want to update your proxy contract with the new implementation contract's address: ${newImplAddress}.`,
modalType: 'modal',
okLabel: 'OK',
cancelLabel: 'Cancel',

@ -8,7 +8,8 @@ const requiredModules = [ // services + layout views + system views
'manager', 'config', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme',
'fileManager', 'contentImport', 'blockchain', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons',
'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider', 'solidity', 'solidity-logic', 'gistHandler', 'layout',
'notification', 'permissionhandler', 'walkthrough', 'storage', 'restorebackupzip', 'link-libraries', 'deploy-libraries', 'openzeppelin-proxy', 'hardhat-provider', 'compileAndRun', 'search']
'notification', 'permissionhandler', 'walkthrough', 'storage', 'restorebackupzip', 'link-libraries', 'deploy-libraries', 'openzeppelin-proxy',
'hardhat-provider', 'compileAndRun', 'search', 'recorder']
const dependentModules = ['git', 'hardhat', 'truffle', 'slither'] // module which shouldn't be manually activated (e.g git is activated by remixd)

@ -5,7 +5,7 @@ const introJs = require('intro.js')
const profile = {
name: 'walkthrough',
displayName: 'Walkthrough',
description: '',
description: 'Remix walkthrough for beginner',
version: packageJson.version,
methods: ['start']
}

@ -98,12 +98,20 @@ export const cancelUpgradeMsg = () => (
export const deployWithProxyMsg = () => (
<div>
NOTE: Deploy With Proxy will initiate two (2) transactions. The first is for the deployment of your implementation contract and the second will be a deployment of an ERC1967 proxy contract.
<b>Deploy with Proxy</b> will initiate two (2) transactions:
<ol className="pl-3">
<li>Deploying the implementation contract</li>
<li>Deploying an ERC1967 proxy contract</li>
</ol>
</div>
)
export const upgradeWithProxyMsg = () => (
<div>
NOTE: Upgrade With Proxy will initiate two (2) transactions. The first is for the deployment of your implementation contract and the second will intiate a call to the upgradeTo function in your proxy contract.
<b>Upgrade with Proxy</b> will initiate two (2) transactions:
<ol className="pl-3">
<li>Deploying the new implementation contract</li>
<li>Updating the proxy contract with the address of the new implementation contract</li>
</ol>
</div>
)

@ -160,8 +160,12 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
const isProxyDeployment = (deployMode || []).find(mode => mode === 'Deploy with Proxy')
const isContractUpgrade = (deployMode || []).find(mode => mode === 'Upgrade with Proxy')
if (isProxyDeployment || isContractUpgrade) {
props.modal('ERC1967', isProxyDeployment ? deployWithProxyMsg() : upgradeWithProxyMsg(), 'Proceed', () => {
if (isProxyDeployment) {
props.modal('Deploy Implementation & Proxy (ERC1967)', deployWithProxyMsg(), 'Proceed', () => {
props.createInstance(loadedContractData, props.gasEstimationPrompt, props.passphrasePrompt, props.publishToStorage, props.mainnetPrompt, isOverSizePrompt, args, deployMode)
}, 'Cancel', () => {})
} else if (isContractUpgrade) {
props.modal('Deploy Implementation & Update Proxy', upgradeWithProxyMsg(), 'Proceed', () => {
props.createInstance(loadedContractData, props.gasEstimationPrompt, props.passphrasePrompt, props.publishToStorage, props.mainnetPrompt, isOverSizePrompt, args, deployMode)
}, 'Cancel', () => {})
} else {

@ -273,7 +273,7 @@ export function ContractGUI (props: ContractGUIProps) {
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title="An ERC1967 proxy contract will be deployed along with the selected implementation contract."
>
Deploy With Proxy
Deploy with Proxy
</label>
</div>
<div>
@ -314,9 +314,9 @@ export function ContractGUI (props: ContractGUIProps) {
htmlFor="upgradeImplementation"
data-id="contractGUIUpgradeImplementationLabel"
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title="The implemetation address will be updated to a new address in the proxy contract."
title="The implementation contract will be deployed and then the proxy contract will be updated with new implementation's address."
>
Upgrade With Proxy
Upgrade with Proxy
</label>
</div>
<span onClick={handleToggleUpgradeImp}>

@ -1,11 +1,12 @@
// eslint-disable-next-line no-use-before-define
import React, {useRef, useState} from 'react'
import React, {useRef, useState, useEffect} from 'react'
import { RecorderProps } from '../types'
import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line
export function RecorderUI (props: RecorderProps) {
const inputLive = useRef<HTMLInputElement>()
const [toggleExpander, setToggleExpander] = useState<boolean>(false)
const [enableRunButton, setEnableRunButton] = useState<boolean>(true)
const triggerRecordButton = () => {
props.storeScenario(props.scenarioPrompt)
}
@ -15,6 +16,11 @@ export function RecorderUI (props: RecorderProps) {
props.runCurrentScenario(liveMode, props.gasEstimationPrompt, props.passphrasePrompt, props.mainnetPrompt)
}
useEffect(() => {
if (props.currentFile.endsWith('.json')) setEnableRunButton(false)
else setEnableRunButton(true)
}, [props.currentFile])
const toggleClass = () => {
setToggleExpander(!toggleExpander)
}
@ -43,24 +49,28 @@ export function RecorderUI (props: RecorderProps) {
<div className={`flex-column ${toggleExpander ? "d-flex" : "d-none"}`}>
<div className="mb-1 mt-1 fmt-2 custom-control custom-checkbox mb-1">
<input ref={inputLive} type="checkbox" id="livemode-recorder" className="custom-control-input custom-select" name="input-livemode"/>
<label className="form-check-label custom-control-label" data-id="runtabLivemodeInput" htmlFor="livemode-recorder">Use live mode (Run transactions against latest compiled contracts).</label>
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="tooltip-livemode-recorder">
<span>If contracts are updated after recording transactions, checking this box<br/>will run recorded transactions with the latest copy of the compiled contracts</span>
</Tooltip>
}>
<label className="form-check-label custom-control-label" data-id="runtabLivemodeInput" htmlFor="livemode-recorder">Run transactions using the latest compilation result</label>
</OverlayTrigger>
</div>
<div className="mb-1 mt-1 udapp_transactionActions">
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="tooltip-save-recorder">
<span>Save {props.count} transaction(s) as scenario file.
</span>
<span>Save {props.count} transaction{props.count === 1 ? '' : 's'} as scenario file</span>
</Tooltip>
}>
<button className="btn btn-sm btn-info savetransaction udapp_recorder" onClick={triggerRecordButton}>Save</button>
<button className="btn btn-sm btn-info savetransaction udapp_recorder" title={props.count === 0 ? 'No transactions to save' : ''} disabled={props.count === 0 ? true: false} onClick={triggerRecordButton}>Save</button>
</OverlayTrigger>
<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="tooltip-run-recorder">
<span>Run transaction(s) from the current scenario file.
</span>
<span>Run transaction(s) from the current scenario file</span>
</Tooltip>
}>
<button className="btn btn-sm btn-info runtransaction udapp_runTxs" data-id="runtransaction" onClick={handleClickRunButton}>Run</button>
<button className="btn btn-sm btn-info runtransaction udapp_runTxs" data-id="runtransaction" title={enableRunButton ? 'No scenario file selected' : ''} disabled={enableRunButton} onClick={handleClickRunButton}>Run</button>
</OverlayTrigger>
</div>
</div>

@ -56,10 +56,11 @@ export function RunTabUI (props: RunTabProps) {
storage: null,
contract: null
})
runTabInitialState.selectExEnv = props.plugin.blockchain.getProvider()
runTabInitialState.selectExEnv = plugin.blockchain.getProvider()
runTabInitialState.selectExEnv = runTabInitialState.selectExEnv === 'vm' ? 'vm-london' : runTabInitialState.selectExEnv
const [runTab, dispatch] = useReducer(runTabReducer, runTabInitialState)
const REACT_API = { runTab }
const currentfile = plugin.config.get('currentFile')
useEffect(() => {
initRunTab(plugin)(dispatch)
@ -249,6 +250,7 @@ export function RunTabUI (props: RunTabProps) {
runCurrentScenario={runScenario}
scenarioPrompt={scenarioPrompt}
count={runTab.recorder.transactionCount}
currentFile={currentfile}
/>
<InstanceContainerUI
instances={runTab.instances}
@ -266,7 +268,7 @@ export function RunTabUI (props: RunTabProps) {
</div>
<ModalDialog id='udappNotify' { ...focusModal } handleHide={ handleHideModal } />
<Toaster message={focusToaster} handleHide={handleToaster} />
<PublishToStorage id='udapp' api={props.plugin} resetStorage={resetStorage} storage={publishData.storage} contract={publishData.contract} />
<PublishToStorage id='udapp' api={plugin} resetStorage={resetStorage} storage={publishData.storage} contract={publishData.contract} />
</Fragment>
)
}

@ -173,6 +173,7 @@ export interface RecorderProps {
passphrasePrompt: (msg: string) => JSX.Element,
scenarioPrompt: (msg: string, defaultValue: string) => JSX.Element,
count: number
currentFile: string
}
export interface InstanceContainerProps {

@ -2,7 +2,7 @@ import React from 'react'
import { bufferToHex, keccakFromString } from 'ethereumjs-util'
import axios, { AxiosResponse } from 'axios'
import { addInputFieldSuccess, cloneRepositoryFailed, cloneRepositoryRequest, cloneRepositorySuccess, createWorkspaceError, createWorkspaceRequest, createWorkspaceSuccess, displayNotification, displayPopUp, fetchWorkspaceDirectoryError, fetchWorkspaceDirectoryRequest, fetchWorkspaceDirectorySuccess, hideNotification, setCurrentWorkspace, setDeleteWorkspace, setMode, setReadOnlyMode, setRenameWorkspace } from './payload'
import { checkSlash, checkSpecialChars, createNonClashingTitle } from '@remix-ui/helper'
import { checkSlash, checkSpecialChars } from '@remix-ui/helper'
import { JSONStandardInput, WorkspaceTemplate } from '../types'
import { QueryParams } from '@remix-project/remix-lib'
@ -333,11 +333,10 @@ export const cloneRepository = async (url: string) => {
const config = plugin.registry.get('config').api
const token = config.get('settings/gist-access-token')
const repoConfig = { url, token }
const urlArray = url.split('/')
let repoName = urlArray.length > 0 ? urlArray[urlArray.length - 1] : ''
try {
repoName = await createNonClashingTitle(repoName, plugin.fileManager)
const repoName = await getRepositoryTitle(url)
await createWorkspace(repoName, 'blank', true, null, true)
const promise = plugin.call('dGitProvider', 'clone', repoConfig, repoName, true)
@ -348,11 +347,11 @@ export const cloneRepository = async (url: string) => {
if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit')
await fetchWorkspaceDirectory(repoName)
dispatch(cloneRepositorySuccess())
}).catch((e) => {
}).catch(() => {
const cloneModal = {
id: 'cloneGitRepository',
title: 'Clone Git Repository',
message: 'An error occured: ' + e,
message: 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin',
modalType: 'modal',
okLabel: 'OK',
okFn: async () => {
@ -370,3 +369,22 @@ export const cloneRepository = async (url: string) => {
dispatch(displayPopUp('An error occured: ' + e))
}
}
export const getRepositoryTitle = async (url: string) => {
const urlArray = url.split('/')
let name = urlArray.length > 0 ? urlArray[urlArray.length - 1] : ''
if (!name) name = 'Undefined'
let _counter
let exist = true
do {
const isDuplicate = await workspaceExists(name + (_counter || ''))
if (isDuplicate) _counter = (_counter || 0) + 1
else exist = false
} while (exist)
const counter = _counter || ''
return name + counter
}

Loading…
Cancel
Save