starts from a copy of strider-git
This commit is contained in:
commit
0c4be005ff
12 files changed
+498
No files matched your search
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
*~
|
||||||
|
*#
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"strict": false,
|
||||||
|
"laxcomma": true,
|
||||||
|
"undef": true,
|
||||||
|
"node": true,
|
||||||
|
"-W033": false,
|
||||||
|
"-W024": false,
|
||||||
|
"-W030": false,
|
||||||
|
"-W069": false,
|
||||||
|
"-W089": false,
|
||||||
|
"-W098": false,
|
||||||
|
"-W116": false,
|
||||||
|
"-W065": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
test: lint
|
||||||
|
@./node_modules/.bin/mocha -R spec
|
||||||
|
|
||||||
|
tolint := *.js *.json lib
|
||||||
|
|
||||||
|
lint:
|
||||||
|
@./node_modules/.bin/jshint --verbose $(tolint)
|
||||||
|
|
||||||
|
.PHONY: test lint watch build less
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
## Git provider
|
||||||
|
|
||||||
|
Allow strider to use any git repository for a project.
|
||||||
|
|
||||||
|
### Config
|
||||||
|
|
||||||
|
- url
|
||||||
|
- display_url (optional)
|
||||||
|
- auth
|
||||||
|
- ssh
|
||||||
|
- custom priv/pubkey if you want
|
||||||
|
- https
|
||||||
|
- username
|
||||||
|
- password
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<label>
|
||||||
|
<span>Url</span>
|
||||||
|
<input required
|
||||||
|
type="text"
|
||||||
|
ng-model="config.url"
|
||||||
|
ng-pattern="/(git|http|https):\/\/.+?/"
|
||||||
|
placeholder="git://example.com/my/repo.git">
|
||||||
|
</label>
|
||||||
|
<div class="auth-type">
|
||||||
|
<h3>Auth type</h3>
|
||||||
|
<div class="btn-group">
|
||||||
|
<div class="btn" ng-model="config.auth.type" required btn-radio="'ssh'">SSH</div>
|
||||||
|
<div class="btn" ng-model="config.auth.type" required btn-radio="'http'">HTTP</div>
|
||||||
|
<div class="btn" ng-model="config.auth.type" required btn-radio="'https'">HTTPS</div>
|
||||||
|
</div>
|
||||||
|
<div ng-show="config.auth.type === 'ssh'">
|
||||||
|
<h4>Ssh Keys</h4>
|
||||||
|
<span class="help-text">
|
||||||
|
Leave these blank to use the project's private and public keys
|
||||||
|
(you can find those under the "General" tab).
|
||||||
|
</span>
|
||||||
|
<div class="row-fluid">
|
||||||
|
<div class="span6">
|
||||||
|
<label>Private Key</label>
|
||||||
|
<textarea ng-required="config.auth.type === 'ssh'" ng-model="config.auth.privkey"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="span6">
|
||||||
|
<label>Public Key</label>
|
||||||
|
<textarea ng-required="config.auth.type === 'ssh'" ng-model="config.auth.pubkey"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div ng-show="config.auth.type.indexOf('http') > -1">
|
||||||
|
<span class="help-text">Http(s) auth</span>
|
||||||
|
<label>
|
||||||
|
<input type="text"
|
||||||
|
ng-required="config.auth.type === 'https'"
|
||||||
|
ng-model="config.auth.username"
|
||||||
|
placeholder="Username">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="password"
|
||||||
|
ng-required="config.auth.type === 'https'"
|
||||||
|
ng-model="config.auth.password"
|
||||||
|
placeholder="Password">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--button ng-click="save()" ng-disabled="saving">Save</button-->
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from mercurial import ui, hg, node
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
peer = hg.peer(ui.ui(), {}, argv[1])
|
||||||
|
for name, rev in peer.branchmap().items():
|
||||||
|
print(name)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from mercurial import ui, hg, node
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
peer = hg.peer(ui.ui(), {}, argv[1])
|
||||||
|
for name, rev in peer.branchmap().items():
|
||||||
|
print(name)
|
||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
|
||||||
|
var gitane = require('gitane')
|
||||||
|
, exec = require('child_process').exec
|
||||||
|
, shellescape = require('shell-escape')
|
||||||
|
, path = require('path')
|
||||||
|
, _ = require('underscore')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
gitUrl: gitUrl,
|
||||||
|
sshUrl: sshUrl,
|
||||||
|
httpUrl: httpUrl,
|
||||||
|
gitCmd: gitCmd,
|
||||||
|
gitaneCmd: gitaneCmd,
|
||||||
|
processBranches: processBranches,
|
||||||
|
getBranches: getBranches,
|
||||||
|
shellEscape: shellEscape
|
||||||
|
}
|
||||||
|
|
||||||
|
function shellEscape(one) {
|
||||||
|
if (!one) {
|
||||||
|
throw new Error('trying to escape nothing', one)
|
||||||
|
}
|
||||||
|
return shellescape([one])
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns [real, safe] urls
|
||||||
|
function gitUrl(config) {
|
||||||
|
return (config.auth.type === 'ssh' ? sshUrl : httpUrl)(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sshUrl(config) {
|
||||||
|
var base = config.url.split('//')[1]
|
||||||
|
, url = shellEscape('git@' + base.replace('/', ':'))
|
||||||
|
return [url, url]
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpUrl(config) {
|
||||||
|
var base = config.url.split('//')[1]
|
||||||
|
, url = config.auth.type + '://' + config.auth.username + ':' + config.auth.password + '@' + base
|
||||||
|
, safe = config.auth.type + '://[username]:[password]@' + base
|
||||||
|
return [url, safe]
|
||||||
|
}
|
||||||
|
|
||||||
|
function gitCmd(cmd, cwd, auth, context, done) {
|
||||||
|
if (auth.type === 'ssh') {
|
||||||
|
return gitaneCmd(cmd, cwd, auth.privkey, context, done)
|
||||||
|
}
|
||||||
|
context.cmd({
|
||||||
|
cmd: cmd,
|
||||||
|
cwd: cwd
|
||||||
|
}, done)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// run a strider command with gitane
|
||||||
|
function gitaneCmd(cmd, dest, privkey, context, done) {
|
||||||
|
var start = new Date()
|
||||||
|
context.status('command.start', { command: cmd, time: start, plugin: context.plugin })
|
||||||
|
gitane.run({
|
||||||
|
emitter: {
|
||||||
|
emit: context.status
|
||||||
|
},
|
||||||
|
cmd: cmd,
|
||||||
|
baseDir: dest,
|
||||||
|
privKey: privkey,
|
||||||
|
detached: true
|
||||||
|
}, function (err, stdout, stderr, exitCode) {
|
||||||
|
var end = new Date()
|
||||||
|
, elapsed = end.getTime() - start.getTime()
|
||||||
|
if (err) {
|
||||||
|
context.log('Gitane error:', err.message)
|
||||||
|
}
|
||||||
|
context.log('gitane command done %s; exit code %s; duration %s', cmd, exitCode, elapsed)
|
||||||
|
context.status('command.done', {exitCode: exitCode, time: end, elapsed: elapsed})
|
||||||
|
done(err ? 500 : exitCode, stdout + stderr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function processBranches(data, done) {
|
||||||
|
done(null, data.trim().split(/\n+/).map(function (line) {
|
||||||
|
return line.split(/\s+/)[1].split('/').slice(-1)[0]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function getBranches(config, privkey, done) {
|
||||||
|
if (config.auth.type === 'ssh') {
|
||||||
|
gitane.run({
|
||||||
|
cmd: 'git ls-remote -h ' + gitUrl(config)[0],
|
||||||
|
baseDir: '/',
|
||||||
|
privKey: config.auth.privkey || privkey,
|
||||||
|
detached: true
|
||||||
|
}, function (err, stdout, stderr, exitCode) {
|
||||||
|
if (err || exitCode !== 0) return done(err || new Error(stderr))
|
||||||
|
processBranches(stdout, done)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
exec('git ls-remote -h ' + httpUrl(config)[0], function (err, stdout, stderr) {
|
||||||
|
if (err) return done(err)
|
||||||
|
processBranches(stdout, done)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMercurialBranches(repoLocation){
|
||||||
|
var pythonScript = path.join(__dirname, 'get_branches.py');
|
||||||
|
var cmd = 'python ' + pythonScript + " " + repoLocation;
|
||||||
|
exec(cmd, function (err, stdout, stderr) {
|
||||||
|
if (err){
|
||||||
|
return console.log(err)
|
||||||
|
}else{
|
||||||
|
return console.log(_.filter(stdout.split("\n"),function(v){return !!v} ))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
getMercurialBranches('ssh://hg@bitbucket.org/ustraca/crypto')
|
||||||
|
console.log("ok?")
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "strider-git",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Strider provider for git repositories",
|
||||||
|
"main": "worker.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "make test"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Strider-CD/strider-git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"strider",
|
||||||
|
"plugin",
|
||||||
|
"provider",
|
||||||
|
"git"
|
||||||
|
],
|
||||||
|
"author": "Jared Forsyth <jared@jaredforsyth.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"readmeFilename": "Readme.md",
|
||||||
|
"strider": {
|
||||||
|
"id": "git",
|
||||||
|
"title": "Git",
|
||||||
|
"type": "provider",
|
||||||
|
"webapp": "webapp.js",
|
||||||
|
"worker": "worker.js",
|
||||||
|
"inline_icon": "code-fork",
|
||||||
|
"config": true
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"gitane": "~0.3.1",
|
||||||
|
"shell-escape": "0.0.1",
|
||||||
|
"mkdirp": "~0.3.5",
|
||||||
|
"underscore": "~1.5.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"jshint": "~2.3.0",
|
||||||
|
"mocha": "~1.13.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Komodo Project File - DO NOT EDIT -->
|
||||||
|
<project id="180948c9-326f-4fe0-8e18-84b6c9ed6e72" kpf_version="5" name="strider-hg.komodoproject">
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
var utils = require('./lib')
|
||||||
|
|
||||||
|
function sanitizeConfig(config) { // v
|
||||||
|
if (!config.auth) return false
|
||||||
|
return {
|
||||||
|
url: config.url,
|
||||||
|
display_url: config.display_url,
|
||||||
|
auth: {
|
||||||
|
type: config.auth.type,
|
||||||
|
privkey: config.auth.privkey,
|
||||||
|
pubkey: config.auth.pubkey,
|
||||||
|
username: config.auth.username,
|
||||||
|
password: config.auth.password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
config: {
|
||||||
|
url: String,
|
||||||
|
display_url: String,
|
||||||
|
auth: {
|
||||||
|
type: { type: String, enum: ['ssh', 'https', 'http'] },
|
||||||
|
privkey: String,
|
||||||
|
pubkey: String,
|
||||||
|
username: String,
|
||||||
|
password: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getBranches: function (userConfig, config, project, done) {
|
||||||
|
utils.getBranches(config, project.privkey, done)
|
||||||
|
},
|
||||||
|
// native git doesn't have a great way to just get a single file at an arbitrary revision
|
||||||
|
fastFile: false,
|
||||||
|
getFile: function (filename, ref, config, project, done) {
|
||||||
|
done(new Error('not implemented'));
|
||||||
|
// utils.gitcmd('git archive --remote=' + url + ' ' + (ref.fetch || ref.id) + ' .strider.json', ...);
|
||||||
|
},
|
||||||
|
routes: function (app, context) {
|
||||||
|
app.get('config', context.auth.requireProjectAdmin, function (req, res) {
|
||||||
|
res.send(req.providerConfig())
|
||||||
|
})
|
||||||
|
app.put('config', context.auth.requireProjectAdmin, function (req, res) {
|
||||||
|
// validate the config
|
||||||
|
var config = sanitizeConfig(req.body)
|
||||||
|
req.providerConfig(config, function (err) {
|
||||||
|
if (err) {
|
||||||
|
res.status(500)
|
||||||
|
return res.send({errors: [err.message]})
|
||||||
|
}
|
||||||
|
res.send({success: true, message: 'Saved git config!', config: config})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
|
||||||
|
var path = require('path')
|
||||||
|
, fs = require('fs')
|
||||||
|
, spawn = require('child_process').spawn
|
||||||
|
, mkdirp = require('mkdirp')
|
||||||
|
|
||||||
|
, utils = require('./lib')
|
||||||
|
|
||||||
|
function safespawn() {
|
||||||
|
var c
|
||||||
|
try {
|
||||||
|
c = spawn.apply(null, arguments)
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Failed to start command: ' + JSON.stringify([].slice.call(arguments)))
|
||||||
|
}
|
||||||
|
c.on('error', function (err) {
|
||||||
|
// suppress node errors
|
||||||
|
})
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpCloneCmd(config, branch) {
|
||||||
|
var urls = utils.httpUrl(config)
|
||||||
|
, screen = 'git clone --recursive ' + urls[1] + ' .'
|
||||||
|
, args = ['clone', '--recursive', urls[0], '.']
|
||||||
|
if (branch) {
|
||||||
|
args = args.concat(['-b', branch])
|
||||||
|
screen += ' -b ' + branch
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
command: 'git',
|
||||||
|
args: args,
|
||||||
|
screen: screen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pull(dest, config, context, done) {
|
||||||
|
context.cmd({
|
||||||
|
cmd: 'git reset --hard',
|
||||||
|
cwd: dest
|
||||||
|
}, function (exitCode) {
|
||||||
|
utils.gitCmd('git pull', dest, config.auth, context, done)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function gitVersion(next) {
|
||||||
|
var child = safespawn('git', ['--version'])
|
||||||
|
, out = ''
|
||||||
|
child.stdout.setEncoding('utf8')
|
||||||
|
child.stderr.setEncoding('utf8')
|
||||||
|
child.stdout.on('data', function (data) {
|
||||||
|
out += data
|
||||||
|
})
|
||||||
|
child.stderr.on('data', function (data) {
|
||||||
|
out += data
|
||||||
|
})
|
||||||
|
child.on('close', function (code) {
|
||||||
|
if (code) return next(new Error('Failed to get git version: ' + out))
|
||||||
|
next(null, out)
|
||||||
|
})
|
||||||
|
child.on('error', function () {})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clone(dest, config, ref, context, done) {
|
||||||
|
if (config.auth.type === 'ssh') {
|
||||||
|
var cmd = 'git clone --recursive ' + utils.sshUrl(config)[0] + ' .'
|
||||||
|
if (ref.branch) {
|
||||||
|
cmd += ' -b ' + ref.branch
|
||||||
|
// this /only/ gets the one branch; so only use if we won't be caching
|
||||||
|
if (!config.cache) cmd += ' --single-branch'
|
||||||
|
}
|
||||||
|
return utils.gitaneCmd(cmd, dest, config.auth.privkey, context, done)
|
||||||
|
}
|
||||||
|
context.cmd({
|
||||||
|
cmd: httpCloneCmd(config),
|
||||||
|
cwd: dest
|
||||||
|
}, done)
|
||||||
|
}
|
||||||
|
|
||||||
|
function badCode(name, code) {
|
||||||
|
var e = new Error(name + ' failed with code ' + code)
|
||||||
|
e.code = code
|
||||||
|
e.exitCode = code
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function (dirs, config, job, done) {
|
||||||
|
return done(null, {
|
||||||
|
config: config,
|
||||||
|
fetch: function (context, done) {
|
||||||
|
module.exports.fetch(dirs.data, config, job, context, done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetch: fetch
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMasterPrivKey(branches) {
|
||||||
|
for (var i=0; i<branches.length; i++) {
|
||||||
|
if (branches[i].name === 'master') {
|
||||||
|
return branches[i].privkey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkoutRef(dest, cmd, ref, done) {
|
||||||
|
return cmd({
|
||||||
|
cmd: 'git checkout -qf ' + utils.shellEscape(ref.id || ref.branch),
|
||||||
|
cwd: dest
|
||||||
|
}, function (exitCode) {
|
||||||
|
done(exitCode && badCode('Checkout', exitCode))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetch(dest, config, job, context, done) {
|
||||||
|
if (config.auth.type === 'ssh' && !config.auth.privkey) {
|
||||||
|
config.auth.privkey = getMasterPrivKey(job.project.branches)
|
||||||
|
}
|
||||||
|
var get = pull
|
||||||
|
, cloning = false
|
||||||
|
, pleaseClone = function () {
|
||||||
|
cloning = true
|
||||||
|
mkdirp(dest, function () {
|
||||||
|
clone(dest, config, job.ref, context, updateCache)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (!config.cache) return pleaseClone()
|
||||||
|
|
||||||
|
context.cachier.get(dest, function (err) {
|
||||||
|
if (err) return pleaseClone()
|
||||||
|
// make sure .git exists
|
||||||
|
fs.exists(path.join(dest, '.git'), function (exists) {
|
||||||
|
if (exists) {
|
||||||
|
context.comment('restored code from cache')
|
||||||
|
return pull(dest, config, context, updateCache)
|
||||||
|
}
|
||||||
|
safespawn('rm', ['-rf', dest]).on('close', function (exitCode) {
|
||||||
|
pleaseClone()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateCache(exitCode) {
|
||||||
|
if (exitCode) return done(badCode('Git ' + (cloning ? 'clone' : 'pull'), exitCode))
|
||||||
|
if (!config.cache) return gotten()
|
||||||
|
context.comment('saved code to cache')
|
||||||
|
context.cachier.update(dest, gotten)
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotten (err) {
|
||||||
|
if (err) return done(err)
|
||||||
|
// fetch the ref
|
||||||
|
if (job.ref.branch && !job.ref.fetch) {
|
||||||
|
return checkoutRef(dest, context.cmd, job.ref, done)
|
||||||
|
}
|
||||||
|
fetchRef(job.ref.fetch, dest, config.auth, context, done)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchRef(what, dest, auth, context, done) {
|
||||||
|
utils.gitCmd('git fetch origin ' + utils.shellEscape(what), dest, auth, context, function (exitCode) {
|
||||||
|
if (exitCode) return done(badCode('Fetch ' + what, exitCode))
|
||||||
|
context.cmd({
|
||||||
|
cmd: 'git checkout -qf FETCH_HEAD',
|
||||||
|
cwd: dest
|
||||||
|
}, function (exitCode) {
|
||||||
|
done(exitCode && badCode('Checkout', exitCode))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user