Created
September 11, 2017 14:31
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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