remote branches

git4refactor
filip mertens 7 months ago
parent aa7d58bad1
commit d843e5c036
  1. 8
      apps/remix-ide/src/app/files/dgitProvider.ts
  2. 2
      libs/remix-ui/git/src/components/buttons/gituibutton.tsx
  3. 19
      libs/remix-ui/git/src/components/buttons/sourcecontrolbuttons.tsx
  4. 9
      libs/remix-ui/git/src/components/navigation/branchedetails.tsx
  5. 7
      libs/remix-ui/git/src/components/panels/commands/fetch.tsx
  6. 1
      libs/remix-ui/git/src/components/panels/commands/merge.tsx
  7. 20
      libs/remix-ui/git/src/components/panels/commands/pushpull.tsx
  8. 5
      libs/remix-ui/git/src/components/panels/commits.tsx
  9. 2
      libs/remix-ui/git/src/components/panels/remotes.tsx
  10. 31
      libs/remix-ui/git/src/lib/gitactions.ts
  11. 2
      libs/remix-ui/git/src/lib/listeners.ts
  12. 12
      libs/remix-ui/git/src/state/gitpayload.ts
  13. 9
      libs/remix-ui/git/src/state/gitreducer.tsx

@ -303,14 +303,14 @@ class DGitProvider extends Plugin {
} }
async getCommitChanges(commitHash1, commitHash2): Promise<commitChange[]> { async getCommitChanges(commitHash1, commitHash2): Promise<commitChange[]> {
//console.log([git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })]) console.log(commitHash1, commitHash2, [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })])
const result: commitChange[] = await git.walk({ const result: commitChange[] = await git.walk({
...await this.addIsomorphicGitConfigFS(), ...await this.addIsomorphicGitConfigFS(),
trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })], trees: [git.TREE({ ref: commitHash1 }), git.TREE({ ref: commitHash2 })],
map: async function (filepath, [A, B]) { map: async function (filepath, [A, B]) {
// ignore directories // ignore directories
//console.log(filepath, A, B) console.log(filepath, A, B)
if (filepath === '.') { if (filepath === '.') {
return return
@ -333,6 +333,8 @@ class DGitProvider extends Plugin {
path: filepath, path: filepath,
} }
console.log('Aoid', Aoid, 'Boid', Boid, commitChange)
// determine modification type // determine modification type
if (Aoid !== Boid) { if (Aoid !== Boid) {
commitChange.type = "modified" commitChange.type = "modified"
@ -340,7 +342,7 @@ class DGitProvider extends Plugin {
if (Aoid === undefined) { if (Aoid === undefined) {
commitChange.type = "deleted" commitChange.type = "deleted"
} }
if (Boid === undefined) { if (Boid === undefined || !commitHash2) {
commitChange.type = "added" commitChange.type = "added"
} }
if (Aoid === undefined && Boid === undefined) { if (Aoid === undefined && Boid === undefined) {

@ -15,7 +15,7 @@ const GitUIButton = ({children, disabledCondition = false, ...rest }:ButtonWithC
const isDisabled = loading || disabledCondition const isDisabled = loading || disabledCondition
return ( return (
<button disabled={loading} {...rest}> <button disabled={isDisabled} {...rest}>
{children} {children}
</button> </button>
); );

@ -86,19 +86,26 @@ export const SourceControlButtons = (props: SourceControlButtonsProps) => {
await actions.push(remote.remote, branch.name) await actions.push(remote.remote, branch.name)
} }
const buttonsDisabled = () => {
return context.upstream === '' || context.remotes.length === 0
}
return (<span className='d-flex justify-content-end align-items-center'> return (
<span className='d-flex justify-content-end align-items-center'>
<CustomTooltip tooltipText={<FormattedMessage id="git.pull" />}> <CustomTooltip tooltipText={<FormattedMessage id="git.pull" />}>
<>{commitsBehind.length}<GitUIButton onClick={pull} className='btn btn-sm'><FontAwesomeIcon icon={faArrowDown} className="" /></GitUIButton></> <>{commitsBehind.length}<GitUIButton disabledCondition={buttonsDisabled()} onClick={pull} className='btn btn-sm'><FontAwesomeIcon icon={faArrowDown} className="" /></GitUIButton></>
</CustomTooltip> </CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.push" />}> <CustomTooltip tooltipText={<FormattedMessage id="git.push" />}>
<>{commitsAhead.length}<GitUIButton onClick={push} className='btn btn-sm'><FontAwesomeIcon icon={faArrowUp} className="" /></GitUIButton></> <>{commitsAhead.length}<GitUIButton disabledCondition={buttonsDisabled()} onClick={push} className='btn btn-sm'><FontAwesomeIcon icon={faArrowUp} className="" /></GitUIButton></>
</CustomTooltip> </CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.sync" />}> <CustomTooltip tooltipText={<FormattedMessage id="git.sync" />}>
<GitUIButton onClick={sync} className='btn btn-sm'><FontAwesomeIcon icon={faArrowsUpDown} className="" /></GitUIButton> <GitUIButton disabledCondition={buttonsDisabled()} onClick={sync} className='btn btn-sm'><FontAwesomeIcon icon={faArrowsUpDown} className="" /></GitUIButton>
</CustomTooltip> </CustomTooltip>
<CustomTooltip tooltipText={<FormattedMessage id="git.refresh" />}> <CustomTooltip tooltipText={<FormattedMessage id="git.refresh" />}>
<GitUIButton onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowRotateRight} className="" /></GitUIButton> <GitUIButton disabledCondition={buttonsDisabled()} onClick={async () => { }} className='btn btn-sm'><FontAwesomeIcon icon={faArrowRotateRight} className="" /></GitUIButton>
</CustomTooltip> </CustomTooltip>
</span>) </span>
)
} }

@ -1,6 +1,7 @@
import { faCaretUp, faCaretDown, faCaretRight, faArrowUp, faArrowDown, faArrowRotateRight, faArrowsUpDown, faGlobe, faCheckCircle, faToggleOff, faToggleOn, faSync } 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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useContext, useEffect } from "react"; import React, { useContext, useEffect } from "react";
import { gitActionsContext } from "../../state/context";
import { branch } from "../../types"; import { branch } from "../../types";
import { gitPluginContext } from "../gitui"; import { gitPluginContext } from "../gitui";
@ -15,6 +16,7 @@ interface BrancheDetailsNavigationProps {
export const BrancheDetailsNavigation = (props: BrancheDetailsNavigationProps) => { export const BrancheDetailsNavigation = (props: BrancheDetailsNavigationProps) => {
const { eventKey, activePanel, callback, branch, checkout } = props; const { eventKey, activePanel, callback, branch, checkout } = props;
const context = React.useContext(gitPluginContext) const context = React.useContext(gitPluginContext)
const actions = React.useContext(gitActionsContext)
const handleClick = () => { const handleClick = () => {
if (!callback) return if (!callback) return
if (activePanel === eventKey) { if (activePanel === eventKey) {
@ -28,6 +30,10 @@ export const BrancheDetailsNavigation = (props: BrancheDetailsNavigationProps) =
window.open(`${branch.remote.url}/tree/${branch.name}`, '_blank'); window.open(`${branch.remote.url}/tree/${branch.name}`, '_blank');
} }
const reloadBranch = () => {
actions.getBranchCommits(branch, 1)
}
return ( return (
<> <>
<div className="d-flex flex-row w-100 mb-2 mt-2"> <div className="d-flex flex-row w-100 mb-2 mt-2">
@ -45,6 +51,9 @@ export const BrancheDetailsNavigation = (props: BrancheDetailsNavigationProps) =
<FontAwesomeIcon className='ml-auto mr-1 pointer' icon={faToggleOn} onClick={() => checkout(branch)}></FontAwesomeIcon> <FontAwesomeIcon className='ml-auto mr-1 pointer' icon={faToggleOn} onClick={() => checkout(branch)}></FontAwesomeIcon>
} }
{branch.remote?.url && <>
<FontAwesomeIcon className='ml-2 pointer' icon={faSync} onClick={() => reloadBranch()}></FontAwesomeIcon></>}
{branch.remote?.url && <> {branch.remote?.url && <>
<FontAwesomeIcon className='ml-2 pointer' icon={faGlobe} onClick={() => openRemote()}></FontAwesomeIcon></>} <FontAwesomeIcon className='ml-2 pointer' icon={faGlobe} onClick={() => openRemote()}></FontAwesomeIcon></>}
</div> </div>

@ -8,11 +8,14 @@ export const Fetch = () => {
const actions = React.useContext(gitActionsContext) const actions = React.useContext(gitActionsContext)
const context = React.useContext(gitPluginContext) const context = React.useContext(gitPluginContext)
const fetchIsDisabled = () => {
return context.upstream === '' || context.remotes.length === 0
}
return ( return (
<> <>
<div className="btn-group w-100" role="group"> <div className="btn-group w-100" role="group">
<GitUIButton type="button" onClick={async () => actions.fetch()} className="btn btn-primary mr-1">Fetch {context.upstream}</GitUIButton> <GitUIButton disabledCondition={fetchIsDisabled()} type="button" onClick={async () => actions.fetch()} className="btn btn-primary mr-1">Fetch {context.upstream}</GitUIButton>
<GitUIButton type="button" onClick={async () => actions.fetch(null, null, context.currentBranch.name, null, true )} className="btn btn-primary">Fetch {context.currentBranch.name}</GitUIButton> <GitUIButton disabledCondition={fetchIsDisabled()} type="button" onClick={async () => actions.fetch(null, null, context.currentBranch.name, null, true )} className="btn btn-primary">Fetch {context.currentBranch.name}</GitUIButton>
</div> </div>
</>) </>)
} }

@ -53,6 +53,7 @@ export const Merge = () => {
<label>Merge from Branch</label> <label>Merge from Branch</label>
<Select <Select
options={localBranchOptions} options={localBranchOptions}
isDisabled={context.branches.length === 0}
onChange={(e: any) => e && onLocalBranchChange(e.value)} onChange={(e: any) => e && onLocalBranchChange(e.value)}
theme={selectTheme} theme={selectTheme}
styles={selectStyles} styles={selectStyles}

@ -36,12 +36,12 @@ export const PushPull = () => {
} }
const onRemoteChange = (value: any) => { const onRemoteChange = (value: any) => {
console.log('onRemoteChange', value) console.log('onRemoteChange', value, context)
actions.setUpstreamRemote(value) actions.setUpstreamRemote(value)
} }
useEffect(() => { useEffect(() => {
console.log('UPSTREAM', context.upstream) console.log('UPSTREAM', context.upstream, context)
}, [context.upstream]) }, [context.upstream])
const onForceChange = (event: any) => { const onForceChange = (event: any) => {
@ -61,7 +61,7 @@ export const PushPull = () => {
useEffect(() => { useEffect(() => {
console.log('context repositories', context.repositories) console.log('context branches', context.branches)
// map context.repositories to options // map context.repositories to options
const localBranches = context.branches && context.branches.length > 0 && context.branches const localBranches = context.branches && context.branches.length > 0 && context.branches
.filter(branch => !branch.remote) .filter(branch => !branch.remote)
@ -93,6 +93,11 @@ export const PushPull = () => {
}, [context.remotes]) }, [context.remotes])
const pushPullIsDisabled = () => {
return localBranch === '' || remoteBranch === '' || context.upstream === '' || context.remotes.length === 0
}
return ( return (
<> <>
@ -100,14 +105,15 @@ export const PushPull = () => {
<div className="btn-group w-100" role="group"> <div className="btn-group w-100" role="group">
<GitUIButton type="button" onClick={async () => pull()} className="btn btn-primary mr-1">Pull</GitUIButton> <GitUIButton disabledCondition={pushPullIsDisabled()} type="button" onClick={async () => pull()} className="btn btn-primary mr-1">Pull</GitUIButton>
<GitUIButton type="button" onClick={async () => push()} className="btn btn-primary">Push</GitUIButton> <GitUIButton disabledCondition={pushPullIsDisabled()} type="button" onClick={async () => push()} className="btn btn-primary">Push</GitUIButton>
</div> </div>
<label>Local Branch</label> <label>Local Branch</label>
<Select <Select
options={localBranchOptions} options={localBranchOptions}
isDisabled={context.branches.length === 0}
onChange={(e: any) => e && onLocalBranchChange(e.value)} onChange={(e: any) => e && onLocalBranchChange(e.value)}
theme={selectTheme} theme={selectTheme}
styles={selectStyles} styles={selectStyles}
@ -119,6 +125,7 @@ export const PushPull = () => {
<label>Remote Branch</label> <label>Remote Branch</label>
<Select <Select
options={remoteBranchOptions} options={remoteBranchOptions}
isDisabled={context.branches.length === 0}
onChange={(e: any) => e && onRemoteBranchChange(e.value)} onChange={(e: any) => e && onRemoteBranchChange(e.value)}
theme={selectTheme} theme={selectTheme}
styles={selectStyles} styles={selectStyles}
@ -127,9 +134,10 @@ export const PushPull = () => {
placeholder="Type to search for a branch..." placeholder="Type to search for a branch..."
/> />
<label>Upstream</label> <label>Remote</label>
<Select <Select
options={localRemotesOptions} options={localRemotesOptions}
isDisabled={context.remotes.length === 0}
onChange={(e: any) => e && onRemoteChange(e.value)} onChange={(e: any) => e && onRemoteChange(e.value)}
theme={selectTheme} theme={selectTheme}
styles={selectStyles} styles={selectStyles}

@ -34,6 +34,9 @@ export const Commits = () => {
await actions.getCommitChanges(commit.oid, commit.commit.parent[0]) await actions.getCommitChanges(commit.oid, commit.commit.parent[0])
} }
const fetchIsDisabled = () => {
return context.upstream === '' || context.remotes.length === 0
}
return ( return (
<> <>
@ -47,7 +50,7 @@ export const Commits = () => {
})} })}
</div> </div>
</div> </div>
{hasNextPage && <GitUIButton className="mb-1 ml-2 btn btn-sm" onClick={loadNextPage}>Load more</GitUIButton>} {hasNextPage && <GitUIButton disabledCondition={fetchIsDisabled()} className="mb-1 ml-2 btn btn-sm" onClick={loadNextPage}>Load more</GitUIButton>}
</> </>
: <div className="text-muted">No commits</div>} : <div className="text-muted">No commits</div>}
</> </>

@ -48,7 +48,7 @@ export const Remotes = () => {
<input placeholder="remote name" name='remotename' onChange={e => onRemoteNameChange(e.target.value)} value={remoteName} className="form-control mb-2" type="text" id="remotename" /> <input placeholder="remote name" name='remotename' onChange={e => onRemoteNameChange(e.target.value)} value={remoteName} className="form-control mb-2" type="text" id="remotename" />
<input placeholder="remote url" name='remoteurl' onChange={e => onUrlChange(e.target.value)} value={url} className="form-control" type="text" id="remoteurl" /> <input placeholder="remote url" name='remoteurl' onChange={e => onUrlChange(e.target.value)} value={url} className="form-control" type="text" id="remoteurl" />
<button className='btn btn-primary mt-1 w-100' onClick={async () => { <button disabled={(remoteName && url)?false:true} className='btn btn-primary mt-1 w-100' onClick={async () => {
addRemote(); addRemote();
}}>add remote</button> }}>add remote</button>
<hr /> <hr />

@ -1,7 +1,7 @@
import { ViewPlugin } from "@remixproject/engine-web"; import { ViewPlugin } from "@remixproject/engine-web";
import { ReadBlobResult, ReadCommitResult } from "isomorphic-git"; import { ReadBlobResult, ReadCommitResult } from "isomorphic-git";
import React from "react"; import React from "react";
import { fileStatus, fileStatusMerge, setRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRateLimit, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog } from "../state/gitpayload"; import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRateLimit, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog } from "../state/gitpayload";
import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType, gitState, branchDifference, remote, gitLog } from '../types'; import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType, gitState, branchDifference, remote, gitLog } from '../types';
import { removeSlash } from "../utils"; import { removeSlash } from "../utils";
import { disableCallBacks, enableCallBacks } from "./listeners"; import { disableCallBacks, enableCallBacks } from "./listeners";
@ -428,6 +428,7 @@ const tokenWarning = async () => {
const parseError = async (e: any) => { const parseError = async (e: any) => {
console.log(e)
// if message conttains 401 Unauthorized, show token warning // if message conttains 401 Unauthorized, show token warning
if (e.message.includes('401')) { if (e.message.includes('401')) {
const result = await plugin.call('notification', 'modal', { const result = await plugin.call('notification', 'modal', {
@ -458,6 +459,13 @@ const parseError = async (e: any) => {
cancelLabel: 'Close', cancelLabel: 'Close',
type: ModalTypes.confirm type: ModalTypes.confirm
}) })
} else if (e.toString().includes('NotFoundError') && !e.toString().includes('fetch')) {
await plugin.call('notification', 'modal', {
title: 'Remote branch not found',
message: 'The branch you are trying to fetch does not exist on the remote.\ If you have forked this branch from another branch, you may need to fetch the original branch first or publish this branch on the remote.',
okLabel: 'OK',
type: ModalTypes.alert
})
} else { } else {
await plugin.call('notification', 'alert', { await plugin.call('notification', 'alert', {
title: 'Error', title: 'Error',
@ -736,7 +744,18 @@ export const diff = async (commitChange: commitChange) => {
export const getCommitChanges = async (oid1: string, oid2: string, branch?: branch, remote?: remote) => { export const getCommitChanges = async (oid1: string, oid2: string, branch?: branch, remote?: remote) => {
console.log(oid1, oid2, branch, remote) console.log(oid1, oid2, branch, remote)
try { try {
// check if oid2 exists
const log = await plugin.call('dGitProvider', 'log', {
ref: branch? branch.name : 'HEAD',
})
if(log) {
const foundCommit = log.find((commit: ReadCommitResult) => commit.oid === oid2)
if(!foundCommit) {
await fetch(remote? remote.remote: null, branch? branch.name: null,null, 5, true, true)
}
}
const result: commitChange[] = await plugin.call('dGitProvider', 'getCommitChanges', oid1, oid2) const result: commitChange[] = await plugin.call('dGitProvider', 'getCommitChanges', oid1, oid2)
dispatch(setCommitChanges(result)) dispatch(setCommitChanges(result))
return result return result
@ -762,6 +781,9 @@ export const fetchBranch = async (branch: branch, page: number) => {
if (!branch.remote || !branch.remote.url) return if (!branch.remote || !branch.remote.url) return
const token = await tokenWarning(); const token = await tokenWarning();
console.log('fetch', branch) console.log('fetch', branch)
if (page == 1) {
dispatch(resetRemoteBranchCommits({ branch }))
}
const { owner, repo } = await getRepoDetails(branch.remote.url); const { owner, repo } = await getRepoDetails(branch.remote.url);
const rc = await plugin.call('dGitProvider' as any, 'remotecommits', { token, owner: owner, repo: repo, branch: branch.name, length, page }); const rc = await plugin.call('dGitProvider' as any, 'remotecommits', { token, owner: owner, repo: repo, branch: branch.name, length, page });
console.log(rc, 'remote commits from octokit') console.log(rc, 'remote commits from octokit')
@ -825,7 +847,7 @@ export const getBranchCommits = async (branch: branch, page: number) => {
const commits: ReadCommitResult[] = await plugin.call('dGitProvider', 'log', { const commits: ReadCommitResult[] = await plugin.call('dGitProvider', 'log', {
ref: branch.name, ref: branch.name,
}) })
try {
const branchDifference: branchDifference = await plugin.call('dGitProvider', 'compareBranches', { const branchDifference: branchDifference = await plugin.call('dGitProvider', 'compareBranches', {
branch, branch,
remote: { remote: {
@ -841,12 +863,15 @@ export const getBranchCommits = async (branch: branch, page: number) => {
{ remote: 'origin', url: '' }, { remote: 'origin', url: '' },
branchDifference: branchDifference branchDifference: branchDifference
})) }))
} catch (e) {
}
dispatch(setLocalBranchCommits({ branch, commits })) dispatch(setLocalBranchCommits({ branch, commits }))
} else { } else {
await fetchBranch(branch, page) await fetchBranch(branch, page)
} }
} catch (e) { } catch (e) {
console.log(e) console.trace(e)
await fetchBranch(branch, page) await fetchBranch(branch, page)
} }
dispatch(setLoading(false)) dispatch(setLoading(false))

@ -196,7 +196,7 @@ export const enableCallBacks = async () => {
} }
const synTimerStart = async () => { const synTimerStart = async () => {
console.trace('synTimerStart') //console.trace('synTimerStart')
if (!callBackEnabled) return if (!callBackEnabled) return
clearTimeout(syncTimer) clearTimeout(syncTimer)
syncTimer = setTimeout(async () => { syncTimer = setTimeout(async () => {

@ -142,6 +142,18 @@ export const setRemoteBranchCommits = ({ branch, commits }:{
} }
} }
export const resetRemoteBranchCommits = ({ branch }:{
branch: branch,
}):{
type: string;
payload: { branch: branch };
} => {
return {
type: 'RESET_REMOTE_BRANCH_COMMITS',
payload: { branch }
}
}
export const setLocalBranchCommits = ({ export const setLocalBranchCommits = ({
branch, branch,
commits commits

@ -119,6 +119,15 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g
commitChanges: [...state.commitChanges] commitChanges: [...state.commitChanges]
} }
case 'RESET_REMOTE_BRANCH_COMMITS':
if (state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name]) {
delete state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name]
}
return {
...state,
remoteBranchCommits: { ...state.remoteBranchCommits }
}
case 'SET_REMOTE_BRANCH_COMMITS': case 'SET_REMOTE_BRANCH_COMMITS':
if (state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name]) { if (state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name]) {
state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name].push(...(action as setRemoteBranchCommitsAction).payload.commits) state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name].push(...(action as setRemoteBranchCommitsAction).payload.commits)

Loading…
Cancel
Save