Skip to content

Commit

Permalink
Merge pull request #152 from cksource/i/148
Browse files Browse the repository at this point in the history
Feature: Added support for tags. Closes #148.
  • Loading branch information
pomek authored Dec 2, 2022
2 parents 4a6f90a + 01b7235 commit be59046
Show file tree
Hide file tree
Showing 28 changed files with 1,597 additions and 341 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

[*.json]
indent_style = space
tab_width = 2
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules/
.nyc_output
coverage/
node_modules/
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,16 @@ Examples:
```

```js
// Clone 'https://github.com/cksource/foo.git' (via HTTPS) and check out to branch tag 'v1.2.3'.
// Clone 'https://github.com/cksource/foo.git' (via HTTPS) and check out to tag 'v1.2.3'.
{
"foo": "https://github.com/cksource/foo.git#v1.2.3"
"foo": "https://github.com/cksource/foo.git@v1.2.3"
}
```

```js
// Clone 'cksource/foo' and check out to the latest available tag.
{
"foo": "cksource/foo@latest"
}
```

Expand Down Expand Up @@ -212,8 +219,9 @@ You can also use full HTTPS URLs to configure `dependencies` in your `mrgit.json
When you call `mrgit sync` or `mrgit co`, mrgit will use the following algorithm to determine the branch to which each repository should be checked out:

1. If a branch is defined in `mrgit.json`, use it. A branch can be defined after `#` in a repository URL. For example: `"@cksource/foo": "cksource/foo#dev"`.
2. If the root repository (assuming, it is a repository) is on one of the "base branches", use that branch name.
3. Otherwise, use `master`.
2. If a tag is defined in `mrgit.json`, use it. A tag can be defined after `@` in a repository URL. Its either a specific tag name, such as `@v30.0.0`, or `@latest` tag that will look for the latest available tag.
3. If the root repository (assuming, it is a repository) is on one of the "base branches", use that branch name.
4. Otherwise, use `master` branch.

You can define the base branches as follows:

Expand Down Expand Up @@ -241,7 +249,7 @@ $ mrgit [command] --help

### sync

Updates dependencies. Switches repositories to correct branches (specified in `mrgit.json`) and pulls changes.
Updates dependencies. Switches repositories to correct branches or tags (specified in `mrgit.json`) and pulls changes.

If any dependency is missing, the command will install this dependency as well.

Expand All @@ -258,8 +266,7 @@ mrgit sync --recursive

### pull

Pulls changes in existing repositories. It does not change branches in the repositories and pull the changes even if
the repository contains uncommitted changes.
Pulls changes in existing repositories. It does not change branches in the repositories. It does not pull the changes if the repository contains uncommitted changes. It skips repositories that are in detached head mode (are checked out on a tag).

Examples:

Expand All @@ -269,7 +276,7 @@ mrgit pull

### push

Pushes changes in existing repositories.
Pushes changes in existing repositories. It skips repositories that are in detached head mode (are checked out on a tag).

Examples:

Expand Down Expand Up @@ -310,8 +317,7 @@ mrgit exec 'echo `pwd`'

### commit (alias: `ci`)

For every repository that contains changes which can be committed, makes a commit with these files.
You need to specify the message for the commit.
For every repository that contains changes which can be committed, makes a commit with these files. You need to specify the message for the commit. It skips repositories that are in detached head mode (are checked out on a tag).

Example:

Expand All @@ -324,10 +330,7 @@ mrgit commit --message 'Introduce PULL_REQUEST_TEMPLATE.md.'

### close

Requires a second argument which is a branch name that will be merged to current one. You can also specify the message
which will be added to the default git-merge message.

Repositories which do not have specified branch will be ignored.
Requires a second argument which is a branch name that will be merged to current one. You can also specify the message which will be added to the default git-merge message. Repositories which do not have specified branch will be ignored. It skips repositories that are in detached head mode (are checked out on a tag).

After merging, the merged branch will be removed from the remote and the local registry.

Expand Down
20 changes: 10 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ function handleCli() {
};

const logo = `
_ _
(_) |
_ __ ___ _ __ __ _ _| |_
_ _
(_) |
_ __ ___ _ __ __ _ _| |_
| '_ \` _ \\| '__| / _\` | | __|
| | | | | | | _ | (_| | | |_
| | | | | | | _ | (_| | | |_
|_| |_| |_|_|(_) \\__, |_|\\__|
__/ |
|___/
__/ |
|___/
`;

const {
Expand All @@ -60,15 +60,15 @@ function handleCli() {
${ c( 'checkout' ) } Changes branches in repositories according to the configuration file.
${ c( 'close' ) } Merges specified branch with the current one and remove merged branch from the remote.
${ c( 'commit' ) } Commits all changes. A shorthand for "mrgit exec 'git commit -a'".
${ c( 'diff' ) } Prints changes from packages where something has changed.
${ c( 'diff' ) } Prints changes from packages where something has changed.
${ c( 'exec' ) } Executes shell command in each package.
${ c( 'fetch' ) } Fetches existing repositories.
${ c( 'pull' ) } Pulls changes in existing repositories.
${ c( 'push' ) } Pushes changes in existing repositories to remotes.
${ c( 'save' ) } Saves hashes of packages in mrgit.json. It allows to easily fix project to a specific state.
${ c( 'status' ) } Prints a table which contains useful information about the status of repositories.
${ c( 'sync' ) } Updates packages to the latest versions or install missing ones.
${ u( 'Options:' ) }
${ y( '--branch' ) } For "${ u( 'save' ) }" command: whether to save branch names.
Expand All @@ -81,7 +81,7 @@ function handleCli() {
Will ignore all packages which names start from "foo".
${ g( 'Default: null' ) }
${ y( '--message' ) } Message that will be used as an option for git command. Required for "${ u( 'commit' ) }"
command but it is also used by "${ u( 'close' ) }" command (append the message to the default).
Expand Down Expand Up @@ -140,7 +140,7 @@ function handleCli() {
return;
}

// Specified command is is available, displays the command's help.
// Specified command is available, displays the command's help.
console.log( logo );
console.log( ` ${ u( 'Command:' ) } ${ c( commandInstance.name || commandName ) } ` );
console.log( commandInstance.helpMessage );
Expand Down
17 changes: 14 additions & 3 deletions lib/commands/close.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ module.exports = {
The merge commit will be made using following message: "${ i( 'Merge branch \'branch-name\'' ) }".
After merging, specified branch will be removed from the remote and local registry.
${ u( 'Options:' ) }
${ m( '--message' ) } (-m) An additional description for merge commit. It will be
${ m( '--message' ) } (-m) An additional description for merge commit. It will be
appended to the default message. E.g.:
${ g( '> mrgit merge develop -- -m "Some description about merged changes."' ) }
`;
Expand All @@ -51,7 +51,7 @@ module.exports = {
const branch = data.arguments[ 0 ];

return execCommand.execute( getExecData( `git branch --list ${ branch }` ) )
.then( execResponse => {
.then( async execResponse => {
const branchExists = Boolean( execResponse.logs.info[ 0 ] );

if ( !branchExists ) {
Expand All @@ -62,6 +62,17 @@ module.exports = {
};
}

const commandResponse = await execCommand.execute( getExecData( 'git branch --show-current' ) );
const detachedHead = !commandResponse.logs.info[ 0 ];

if ( detachedHead ) {
log.info( 'This repository is currently in detached head mode - skipping.' );

return {
logs: log.all()
};
}

const mergeMessage = this._getMergeMessage( data.toolOptions, data.arguments );
const commitTitle = `Merge branch '${ branch }'`;

Expand Down
14 changes: 11 additions & 3 deletions lib/commands/commit.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ module.exports = {

return `
${ u( 'Description:' ) }
Makes a commit in every repository that contains tracked files that have changed.
Makes a commit in every repository that contains tracked files that have changed.
This command is a shorthand for: "${ i( 'mrgit exec \'git commit -a\'' ) }".
${ u( 'Options:' ) }
${ y( '--message' ) } (-m) Required. A message for the commit. It can be specified more then once, e.g.:
${ g( '> mrgit commit --message "Title of the commit." --message "Additional description."' ) }
${ u( 'Git Options:' ) }
${ u( 'Git Options:' ) }
${ m( '--no-verify' ) } (-n) Whether to skip pre-commit and commit-msg hooks.
${ g( '> mrgit commit -m "Title of the commit." -- -n' ) }
`;
Expand Down Expand Up @@ -62,6 +62,14 @@ module.exports = {
.then( execResponse => {
const status = gitStatusParser( execResponse.logs.info[ 0 ] );

if ( status.detachedHead ) {
log.info( 'This repository is currently in detached head mode - skipping.' );

return {
logs: log.all()
};
}

if ( !status.anythingToCommit ) {
log.info( 'Nothing to commit.' );

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = {
return `
${ u( 'Description:' ) }
Requires a command that will be executed on all repositories. E.g. "${ g( 'mrgit exec pwd' ) }" will execute "${ i( 'pwd' ) }"
command in every repository. Commands that contain spaces must be wrapped in quotation marks,
command in every repository. Commands that contain spaces must be wrapped in quotation marks,
e.g.: "${ g( 'mrgit exec "git remote"' ) }".
`;
},
Expand Down
14 changes: 13 additions & 1 deletion lib/commands/pull.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module.exports = {
* @param {CommandData} data
* @returns {Promise}
*/
execute( data ) {
async execute( data ) {
const execCommand = require( './exec' );

const destinationPath = path.join( data.toolOptions.packages, data.repository.directory );
Expand All @@ -39,6 +39,18 @@ module.exports = {
return Promise.resolve( {} );
}

const commandResponse = await execCommand.execute( getExecData( 'git branch --show-current' ) );
const currentlyOnBranch = Boolean( commandResponse.logs.info[ 0 ] );

if ( !currentlyOnBranch ) {
return Promise.resolve( {
logs: {
error: [],
info: [ 'This repository is currently in detached head mode - skipping.' ]
}
} );
}

return execCommand.execute( getExecData( 'git pull' ) );

function getExecData( command ) {
Expand Down
18 changes: 15 additions & 3 deletions lib/commands/push.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ module.exports = {
For cloned repositories this command is a shorthand for: "${ i( 'mrgit exec \'git push\'' ) }".
${ u( 'Git Options:' ) }
All options accepted by "${ i( 'git push' ) }" are supported by mrgit. Everything specified after "--" is passed directly to the
All options accepted by "${ i( 'git push' ) }" are supported by mrgit. Everything specified after "--" is passed directly to the
"${ i( 'git push' ) }" command.
E.g.: "${ g( 'mrgit push -- --verbose --all' ) }" will execute "${ i( 'git push --verbose --all' ) }"
`;
},
Expand All @@ -36,7 +36,7 @@ module.exports = {
* @param {CommandData} data
* @returns {Promise}
*/
execute( data ) {
async execute( data ) {
const execCommand = require( './exec' );

const destinationPath = path.join( data.toolOptions.packages, data.repository.directory );
Expand All @@ -46,6 +46,18 @@ module.exports = {
return Promise.resolve( {} );
}

const commandResponse = await execCommand.execute( getExecData( 'git branch --show-current' ) );
const currentlyOnBranch = Boolean( commandResponse.logs.info[ 0 ] );

if ( !currentlyOnBranch ) {
return Promise.resolve( {
logs: {
error: [],
info: [ 'This repository is currently in detached head mode - skipping.' ]
}
} );
}

const pushCommand = ( 'git push ' + data.arguments.join( ' ' ) ).trim();

return execCommand.execute( getExecData( pushCommand ) );
Expand Down
10 changes: 7 additions & 3 deletions lib/commands/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ module.exports = {

return `
${ u( 'Description:' ) }
Saves hashes of commits or branches which repositories are checked out in "mrgit.json" file.
Saves hashes of commits or branches which repositories are checked out in "mrgit.json" file.
${ u( 'Options:' ) }
${ y( '--hash' ) } Whether to save hashes (id of last commit) on current branch.
${ y( '--hash' ) } Whether to save hashes (id of last commit) on current branch.
${ g( 'Default: true' ) }
${ y( '--branch' ) } (-b) Whether to save names of current branches instead of commit ids.
${ g( 'Default: false' ) }
Expand Down Expand Up @@ -104,9 +104,13 @@ module.exports = {
const cwd = require( '../utils/getcwd' )();
const mrgitJsonPath = path.join( cwd, 'mrgit.json' );

const tagPattern = /@([^ ~^:?*\\]*?)$/;

updateJsonFile( mrgitJsonPath, json => {
for ( const response of commandResponses.values() ) {
const repository = json.dependencies[ response.packageName ].split( '#' )[ 0 ];
const repository = json.dependencies[ response.packageName ]
.replace( tagPattern, '' )
.split( '#' )[ 0 ];

// If returned branch is equal to 'master', save only the repository path.
if ( response.branch && response.data === 'master' ) {
Expand Down
Loading

0 comments on commit be59046

Please sign in to comment.