Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI Simplification #10

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: node_js
node_js:
- "0.12"
- "4.2"
- "5.5"
script: npm run test
- "4"
- "5"
- "6"
script: npm test
44 changes: 20 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Version][version-badge]][version-href]
[![Build status][build-badge]][build-href]

Push the contents of a directory to a remote branch
`git push`, but for directories

* No messing around with `.gitignore` (no need to commit the directory)
* Perfect for pushing a `dist`/`build` directory to `gh-pages`
Expand All @@ -17,41 +17,37 @@ npm install push-dir
## example

```
push-dir --dir=build --branch=gh-pages
push-dir build:gh-pages
```

## usage

```
Usage: push-dir {OPTIONS}

Required Options:

--dir
The name of the directory whose contents will be committed to branch
```usage
usage: push-dir [remote] <dir>:<branch> [options...]

--branch
The name of the remote branch to push to
required:

Advanced Options:
dir
the name of the directory whose contents will be pushed to <branch>

--remote
The name of the remote to push to (defaults to origin)
branch
the name of the remote branch to push to

--cleanup
whether to delete the local branch after creating
optional:

--local-branch-name
force the name of the local branch that is pushed to the remote branch
remote
the name of the remote to push to
defaults to: origin

--allow-unclean
whether to attempt push even if git unclean
--preserve-local-temp-branch
keep the local temp branch after pushing
defaults to: false

--overwrite-local
whether to override a local branch of the same name, if exists
--help, -h
display this message

--force
alias for both --allow-unclean and --overwrite-local
--message, -m
name of commit message
```


Expand Down
42 changes: 40 additions & 2 deletions bin/push-dir.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,44 @@
#!/usr/bin/env node

var minimist = require('minimist');
var pushDir = require('../index.js');

var opts = require('minimist')(process.argv.slice(2));
pushDir(opts);
var argv = minimist(process.argv.slice(2), {
string: ['message'],
boolean: ['preserve-local-temp-branch', 'help'],
alias: {
'help': 'h',
'message': 'm'
}
});

if (argv.help) {
showUsage();
process.exit(0);
}

var numArgs = argv._.length;

if (!numArgs || numArgs > 2) {
showUsage();
process.exit(1);
}

var remoteSpecified = numArgs === 2;
var dirBranch = remoteSpecified ? argv._[1] : argv._[0];
var dir = dirBranch.split(':').slice(0, -1).join(':');
var branch = dirBranch.split(':').slice(-1)[0];
var options = {
remote: remoteSpecified ? argv._[0] : undefined,
preserveLocalTempBranch: argv['preserve-local-temp-branch'],
message: argv['message']
};

pushDir(dir, branch, options);

function showUsage() {
var path = require('path');
var fs = require('fs');
fs.createReadStream(path.join(__dirname, 'usage.txt'))
.pipe(process.stdout);
}
25 changes: 25 additions & 0 deletions bin/usage.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
usage: push-dir [remote] <dir>:<branch> [options...]

required:

dir
the name of the directory whose contents will be pushed to <branch>

branch
the name of the remote branch to push to

optional:

remote
the name of the remote to push to
defaults to: origin

--preserve-local-temp-branch
keep the local temp branch after pushing
defaults to: false

--help, -h
display this message

--message, -m
name of commit message
109 changes: 56 additions & 53 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,35 @@ var exec = require('child_process').exec;

module.exports = pushDir;

function pushDir(opts) {
getLastCommitInfo().then(function(info) {
var hash = info.hash;
var detachedHead = info.branch === '';
var originalBranch = detachedHead ? hash : info.branch;

var directory = opts.dir;
var local = opts.branch + '-' + hash;
var remote = opts.remote || 'origin';
var remoteBranch = opts.branch;
var message = typeof opts.message === 'function' ?
opts.message(hash) : opts.message || hash;
var allowUnclean = opts['allow-unclean'] || opts.force;
var overwriteLocal = opts['overwrite-local'] || opts.force;
var cleanup = opts.cleanup === undefined ? false : opts.cleanup;

Promise.resolve()
.then(checkIfClean)
.catch(function onUnclean(reason) {
return allowUnclean ?
console.log('ignoring unclean git...') : Promise.reject(reason);
})

.then(noLocalBranchConflict.bind(null, local))
.catch(function onBranchConflict(reason) {
return overwriteLocal ?
overwriteLocalBranch(local) : Promise.reject(reason);
})

.then(checkoutOrphanBranch.bind(null, directory, local))
.then(addDir.bind(null, directory))
.then(commitDir.bind(null, directory, message))
.then(pushDirToRemote.bind(null, remote, remoteBranch))
.then(resetBranch.bind(null, originalBranch, detachedHead))
.then(cleanup ? deleteLocalBranch.bind(null, local) : null)
.catch(handleError);

}, handleError);
function pushDir(dir, branch, options) {
return getLastCommitInfo(options.message)
.then(function(info) {
var hash = info.hash;
var message = info.message || hash;
var detachedHead = info.branch === '';
var originalBranch = detachedHead ? hash : info.branch;

var local = branch + '-' + hash;
var remote = options.remote || 'origin';
var cleanup = !options.preserveLocalTempBranch;

return Promise.resolve()
.then(checkIfClean)
.then(noLocalBranchConflict.bind(null, local))
.then(checkoutOrphanBranch.bind(null, dir, local))
.then(addDir.bind(null, dir))
.then(commitDir.bind(null, dir, message))
.then(pushDirToRemote.bind(null, remote, branch))
.then(resetBranch.bind(null, originalBranch, detachedHead))
.then(cleanup ? deleteLocalBranch.bind(null, local) : null);
})
.catch(handleError);
}

/**
* Tasks
*/

function overwriteLocalBranch(local) {
console.log('will overwite local branch...');
return deleteLocalBranch(local);
}

function checkIfClean() {
return expectOutputEmpty(
'git status --porcelain',
Expand All @@ -63,10 +43,18 @@ function checkIfClean() {
* @return {string} - name of current branch
*/
function getCurrentBranch() {
return execCmd(
'git symbolic-ref HEAD -q | sed -e "s/^refs\\/heads\\///"',
'problem getting current branch'
);
return Promise.resolve()
.then(function() {
return execCmd(
'git symbolic-ref HEAD -q',
'problem getting current branch',
true
);
})
.then(function(ref) {
var regex = new RegExp('^refs\/heads\/');
return ref.replace(regex, '');
});
}

function resetBranch(branch, detach) {
Expand All @@ -84,9 +72,17 @@ function addDir(directory) {
);
}

function formatMessage(message) {
return message ? execCmd(
'git log -1 --pretty=\'format:' + escapeSingle(message) + '\'',
'error formatting commit message'
) : '';
}

function commitDir(directory, message) {
var escaped = escapeSingle(message);
return execCmd(
'git --work-tree ' + directory + ' commit -m "' + message + '"',
'git --work-tree ' + directory + ' commit -m \'' + escaped + '\'',
'problem committing directory to local branch'
);
}
Expand Down Expand Up @@ -119,17 +115,19 @@ function noLocalBranchConflict(branch) {
);
}

function getLastCommitInfo() {
function getLastCommitInfo(message) {
return Promise
.all([
getLastCommitHash(),
getCurrentBranch()
getCurrentBranch(),
formatMessage(message)
])
.then(function(info) {
info = info.map(function(s) { return s.trim(); });
return {
hash: info[0],
branch: info[1]
branch: info[1],
message: info[2]
};
});
}
Expand All @@ -150,10 +148,10 @@ function handleError(err) {
process.exit(1);
}

function execCmd(cmd, errMessage) {
function execCmd(cmd, errMessage, allowError) {
return new Promise(function(resolve, reject) {
exec(cmd, function(error, stdout, stderr) {
error ? reject(errMessage) : resolve(stdout);
(error && allowError !== true) ? reject(errMessage) : resolve(stdout);
});
});
}
Expand All @@ -165,3 +163,8 @@ function expectOutputEmpty(cmd, errMessage) {
});
});
}

var single = /'/g;
function escapeSingle(str) {
return str.replace(single, '\'"\'"\'');
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "push-dir",
"version": "0.2.1",
"description": "Push a directory to a remote branch",
"keywords": [],
"contributors": [
"Ryan Tsao <[email protected]>",
"Scott Hardy <[email protected]>"
Expand Down
38 changes: 38 additions & 0 deletions test/fixture/test-abort-bad-args.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash

git remote add origin ../fixture-remote/.git


# no args
node $PUSH_DIR
if [ $? -ne 1 ]; then
exit 1
fi


# just dir
node $PUSH_DIR build
if [ $? -ne 1 ]; then
exit 2
fi


# just remote + dir
node $PUSH_DIR origin build
if [ $? -ne 1 ]; then
exit 3
fi


# empty branch
node $PUSH_DIR build:
if [ $? -ne 1 ]; then
exit 4
fi


# colon branch
node $PUSH_DIR build::
if [ $? -ne 1 ]; then
exit 5
fi
4 changes: 2 additions & 2 deletions test/fixture/test-abort-branch-exists.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
git remote add origin ../fixture-remote/.git


node $PUSH_DIR --dir build --branch gh-pages
node $PUSH_DIR build:gh-pages --preserve-local-temp-branch
if [ $? -ne 0 ]; then
exit 1
fi


node $PUSH_DIR --dir build --branch gh-pages
node $PUSH_DIR build:gh-pages
if [ $? -ne 1 ]; then
exit 2
fi
2 changes: 1 addition & 1 deletion test/fixture/test-abort-staged-changes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ echo "yolo" > yolo.js
git add yolo.js


node $PUSH_DIR --dir build --branch gh-pages
node $PUSH_DIR build:gh-pages
if [ $? -ne 1 ]; then
exit 1
fi
Loading