-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* yada * finish branch new * testing testing * fixes * fix tests * fix formatting
- Loading branch information
Showing
11 changed files
with
203 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import ErrorDisplay from '../../components/error-display.js'; | ||
import React, { useCallback } from 'react'; | ||
import { Action, useAction } from '../../hooks/use-action.js'; | ||
import { CommandConfig, CommandProps } from '../../types.js'; | ||
import { Text } from 'ink'; | ||
import { safeBranchNameFromCommitMessage } from '../../utils/naming.js'; | ||
import { useGit } from '../../hooks/use-git.js'; | ||
|
||
function BranchNew({ input }: CommandProps) { | ||
const [, , message] = input; | ||
// todo: refactor to a sanitize input pattern | ||
const result = useBranchNew({ message: message! }); | ||
|
||
if (result.isError) { | ||
return <ErrorDisplay error={result.error} />; | ||
} | ||
|
||
if (result.isLoading) { | ||
return <Text color="cyan">Loading...</Text>; | ||
} | ||
|
||
return ( | ||
<Text bold color="green"> | ||
New branch created - {result.branchName} | ||
</Text> | ||
); | ||
} | ||
|
||
type UseBranchNewAction = Action & { | ||
branchName: string; | ||
}; | ||
|
||
const useBranchNew = ({ message }: { message: string }): UseBranchNewAction => { | ||
const git = useGit(); | ||
|
||
const branchName = safeBranchNameFromCommitMessage(message); | ||
|
||
const performAction = useCallback(async () => { | ||
await git.createBranch({ branchName }); | ||
await git.checkout(branchName); | ||
await git.addAllFiles(); | ||
await git.commit({ message }); | ||
}, [branchName]); | ||
|
||
const action = useAction({ | ||
asyncAction: performAction, | ||
}); | ||
|
||
return { | ||
isLoading: action.isLoading, | ||
isError: action.isError, | ||
error: action.error, | ||
branchName, | ||
} as UseBranchNewAction; | ||
}; | ||
|
||
export const branchNewConfig: CommandConfig = { | ||
description: | ||
'Create a new branch, switch to it, and commit all current changes to it', | ||
usage: 'branch new "<message>"', | ||
key: 'new', | ||
aliases: ['n'], | ||
validateProps: (props) => { | ||
const { input } = props; | ||
const [, , message] = input; | ||
|
||
if (!message) | ||
return { | ||
valid: false, | ||
errors: ['Please provide a commit message'], | ||
}; | ||
|
||
return { valid: true }; | ||
}, | ||
}; | ||
|
||
export default BranchNew; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { useEffect, useState } from 'react'; | ||
|
||
export const useAction = ({ | ||
asyncAction, | ||
}: { | ||
asyncAction: () => Promise<void>; | ||
}): Action => { | ||
const [state, setState] = useState<State>({ type: 'LOADING' }); | ||
|
||
useEffect(() => { | ||
asyncAction() | ||
.then(() => setState({ type: 'COMPLETE' })) | ||
.catch((e: Error) => { | ||
setState({ type: 'ERROR', error: e }); | ||
}); | ||
}, [asyncAction]); | ||
|
||
if (state.type === 'ERROR') { | ||
return { | ||
isLoading: false, | ||
isError: true, | ||
error: state.error, | ||
}; | ||
} | ||
|
||
return { | ||
isLoading: state.type === 'LOADING', | ||
isError: false, | ||
error: undefined, | ||
}; | ||
}; | ||
|
||
export type Action = | ||
| { | ||
isLoading: boolean; | ||
isError: false; | ||
error: undefined; | ||
} | ||
| { | ||
isLoading: boolean; | ||
isError: true; | ||
error: Error; | ||
}; | ||
|
||
// export type Action = { isLoading: boolean } & ErrorResult; | ||
|
||
export type State = | ||
| { | ||
type: 'LOADING'; | ||
} | ||
| { | ||
type: 'COMPLETE'; | ||
} | ||
| { | ||
type: 'ERROR'; | ||
error: Error; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
import { safeBranchNameFromCommitMessage } from './naming.js'; | ||
|
||
describe('safeBranchNameFromCommitMessage is working normally', () => { | ||
it('it converts commit messages to branch names as expected', () => { | ||
expect( | ||
safeBranchNameFromCommitMessage( | ||
'name/fix(module-test): do cool things [ENG-1111]' | ||
) | ||
).to.equal('name/fix_module-test_do_cool_things_eng-1111_'); | ||
}); | ||
it('handles special characters', () => { | ||
// this is just an arbitrary string containing random special characters | ||
expect( | ||
safeBranchNameFromCommitMessage( | ||
'!"#$%&\'()*+,.:;<=>?@[\\]^{}~‒–—―‘’“”«»…〈〉【】《》+−*=≠≤≥±∞≈×÷∑∫∂∇√$¢£€¥₣₤₹₱₩§¶©®™℅℗∴¨^`´~¯ˇ˘˙˚˛←→↑↓↔↕↖↗↘↙♪♩♫♬☼☽☾☀☁☂☃✓✔✕✖✗✘┌┐└┘├┤┬┴┼─│█▀▄▌▐░▒▓★☆☎☏☑❄❅❆☐🙂❤️👍\n' | ||
) | ||
).to.equal('_'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export const safeBranchNameFromCommitMessage = (message: string): string => { | ||
// todo: how to handle exact branch matches | ||
// Match every non-alphanumeric character that is not "-" or "_" | ||
const pattern = /[^a-zA-Z0-9\-_\/]+/gm; | ||
return message.replace(pattern, '_').toLowerCase(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters