Skip to content

Instantly share code, notes, and snippets.

@deecewan
Created September 11, 2017 14:31
Show Gist options
  • Save deecewan/dc7e726246ff24a06026d87ea9c20c90 to your computer and use it in GitHub Desktop.
Save deecewan/dc7e726246ff24a06026d87ea9c20c90 to your computer and use it in GitHub Desktop.
move all folders from root-level folder into repo-dependent folders, like Go's package manager
const fs = require('fs-extra');
const path = require('path');
function isRepo(folder) {
const contents = fs.readdirSync(folder);
return contents.includes('.git');
}
function parseConfig(config) {
const output = {}
const split = Array.from(config)
let currentIndex = 0;
let currentToken = "";
let currentObjectName = "";
let currentObject = {};
while (currentIndex < split.length) {
const char = split[currentIndex]
if (char === '\n' || char === "\t") {
// ignore
currentIndex++;
continue;
}
if (char === "[") {
// seal object from before
if (currentObjectName) {
output[currentObjectName] = currentObject;
currentObjectName = '';
currentObject = {};
}
// process new object.
// we can skip the opening brace
currentIndex++;
while (split[currentIndex] !== "]") {
currentObjectName += split[currentIndex];
currentIndex++;
}
// skip the closing brace
currentIndex++;
continue;
}
// process the object
let key = '';
let value = '';
// of the form 'key = value',
// so stop when the next two characters are ' ='
while (split[currentIndex] !== " " && split[currentIndex + 1] !== "=") {
// this is the key
key += split[currentIndex];
currentIndex++;
}
// skip the ' = '
currentIndex += 3;
while (split[currentIndex] !== "\n") {
// this is the value
value += split[currentIndex];
currentIndex++;
}
currentObject[key] = value;
}
output[currentObjectName] = currentObject;
currentObjectName = '';
currentObject = {};
return output;
}
function parseGitUrl(url) {
const matches = url.match(/(:|\/)([a-zA-Z\-_]+)\//)
return { parent: matches[2] };
}
function getGitUrl(folder) {
const config = fs.readFileSync(path.join(__dirname, folder, '.git', 'config'), 'utf8');
const parsed = parseConfig(config);
const remote = parsed['remote "origin"']
if (!remote) {
return null
}
return remote.url
}
fs.readdir(__dirname, (err, files) => {
if (err) throw err;
const toProcess = files.map(file => {
const stat = fs.statSync(file);
if (stat.isDirectory()) {
if (!isRepo(file)) {
return;
}
const url = getGitUrl(file);
if (!url) { return; }
const parent = parseGitUrl(url).parent;
const moveTo = path.join(__dirname, parent, file);
return ({
parent,
from: path.join(__dirname, file),
to: path.join(__dirname, parent, file)
});
}
})
.reduce((acc, curr) => acc.concat(curr ? curr : []), [])
.reduce((acc, { parent, ...rest }) => {
return { ...acc, [parent]: [].concat(acc[parent] || []).concat(rest)}
}, {});
Object.entries(toProcess).forEach(([topLevel, folders]) => {
fs.ensureDir(path.join(__dirname, topLevel));
folders.map(folder => {
console.log('Copying', folder.from, 'to', folder.to)
fs.copySync(folder.from, folder.to, {
overwrite: false,
errorOnExist: true,
});
return from;
})
.map(from => fs.remove(from))
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment