Skip to content

Commit

Permalink
Merge pull request mixu#59 from timja-kainos/feature/export
Browse files Browse the repository at this point in the history
Export and import config plugins
  • Loading branch information
mixu committed Jan 30, 2017
2 parents a1e5d37 + 66fc9b7 commit de8c900
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 1 deletion.
10 changes: 9 additions & 1 deletion bin/gr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ require('minilog').enable();

var config = require('../plugins/config.js'),
tag = require('../plugins/tag.js'),
status = require('../plugins/status.js');
status = require('../plugins/status.js'),
exportPlugin = require('../plugins/export.js'),
importPlugin = require('../plugins/import.js');

function version(req) {
console.log(require('../package.json').version);
Expand Down Expand Up @@ -62,6 +64,12 @@ gr.use(['tag'], tag.list);
// for usability: gr discover should run gr tag discover
gr.use(['discover'], tag.discover);

// export plugin
gr.use('export', exportPlugin.exportAsJson);

// import plugin
gr.use('import', importPlugin.importFromJson);

// default: run the remainder as a shell task
gr.use('--', require('../plugins/run.js'));
gr.use(require('../plugins/run.js'));
Expand Down
2 changes: 2 additions & 0 deletions bin/usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,7 @@ gr config ..
rm <k> <v> Remove a value from a config key (if it exists)
list List all configuration (default action)

gr export <path-to-export> Export your grconfig in a consumable way for other people.
gr import <file> Import from a previously exported grconfig.
gr help Show this help
gr version Version info
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
"gr": "./bin/gr"
},
"dependencies": {
"async": "^2.1.4",
"lodash.groupby": "^4.6.0",
"minilog": "~2.0.2",
"simple-git": "^1.65.0",
"tabtab": "git+https://github.com/mixu/node-tabtab.git"
},
"devDependencies": {
Expand Down
111 changes: 111 additions & 0 deletions plugins/export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
'use strict';

const run = require('../lib/run');

const git = require('simple-git');

const groupBy = require('lodash.groupby');

const async = require('async');
const path = require('path');


function getProjectName(path) {
const split = path.split('/');
return split[split.length - 1]
}

function exportAsJson(req, res, next) {
const exportPath = process.argv[3];
if (!exportPath) {
return console.log('Please supply a file path of where you want to start exporting from')
}
const absoluteExportPath = path.resolve(exportPath);

let exportedConfig = {
repos: []
};

const getRelativeRepoPath = function (projectName, path) {
const exportPathRemoved = path.substring(absoluteExportPath.length, path.length);
const relativePath = exportPathRemoved.substring(1, exportPathRemoved.length - projectName.length - 1);

return relativePath === '/' ? '.' : relativePath;
};

const getRepoDetails = function (path, tag, callback) {
git(path).listRemote(['--get-url'], function (err, gitUrl) {
if (err) {
console.log('Error with: ' + path);
return callback(err)
}
const projectName = getProjectName(path);
const repo = {
name: projectName,
url: gitUrl.trim(),
tag: tag,
path: getRelativeRepoPath(projectName, path)
};
exportedConfig.repos.push(repo);
callback()
});
};

const tags = req.config.items.tags;

if (!tags) {
console.log('Cannot export if there is no config');
return req.exit()
}

const tagKeys = Object.keys(tags);
const filteredTags = {};

tagKeys.forEach((tagName) => {
filteredTags[tagName] = tags[tagName].filter((path) => path.indexOf(absoluteExportPath) > -1);
});


let requests = [];
tagKeys.forEach(function (tagName) {
requests = requests.concat(filteredTags[tagName].map((path) => {
return function (callback) {
getRepoDetails(path, tagName, callback);
};
}));
});
async.parallel(requests, (err, result) => {
if (err) {
console.log('Error exporting config');
return req.exit();
}
const groupedConfig = groupBy(exportedConfig.repos, 'url');

const groupedConfigKeys = Object.keys(groupedConfig);
let newConfig = {
repos: []
};

groupedConfigKeys.forEach((key) => {
let tags = [];
const repos = groupedConfig[key];
repos.forEach((repo) => tags.push(repo.tag));
let newRepo = {
name: repos[0].name,
url: key,
tags: tags,
path: repos[0].path
};
newConfig.repos.push(newRepo)
});

console.log(JSON.stringify(newConfig));
});

req.exit();
}

module.exports = {
exportAsJson: exportAsJson

};
54 changes: 54 additions & 0 deletions plugins/import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

const run = require('../lib/run');

const git = require('simple-git');

const async = require('async');

const fs = require('fs');
const path = require('path');

function importFromJson(req, res, next) {
const filePath = process.argv[3];
if (!filePath) {
console.log('Please supply a file path for your import');
return req.exit();
}

const cloneRepo = (repo, callback) => {
console.log(`Cloning ${repo.name} into ${repo.path}/${repo.name}`);
git(repo.path).clone(repo.url, repo.name, (err, result) => {
if (err) {
console.log(`Failed to clone ${repo.name}`);
return callback(err)
}
});
repo.tags.forEach((tag) => req.config.add(`tags.${tag}`, path.resolve(repo.path, repo.name)));
callback();
};

const exportedFile = JSON.parse(fs.readFileSync(filePath, 'utf8'));

let cloneRequests = [];
exportedFile.repos.forEach((repo) => {
cloneRequests.push((callback) => {
cloneRepo(repo, callback);
})
});

async.parallel(cloneRequests, (err, result) => {
if (err) {
return console.log(err);
}

req.config.save();
console.log('Successfully imported new config');
});

req.exit();
}

module.exports = {
importFromJson: importFromJson
};

0 comments on commit de8c900

Please sign in to comment.