tuture
Version:
Write tutorials from the future, with the power of Git and community.
142 lines (141 loc) • 5.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
const path_1 = tslib_1.__importDefault(require("path"));
const logger_1 = tslib_1.__importDefault(require("./logger"));
const git_1 = require("./git");
const constants_1 = require("../constants");
const assets_1 = require("./assets");
exports.collectionPath = path_1.default.join(process.env.TUTURE_PATH || process.cwd(), constants_1.TUTURE_ROOT, constants_1.COLLECTION_PATH);
exports.collectionCheckpoint = path_1.default.join(process.env.TUTURE_PATH || process.cwd(), constants_1.TUTURE_ROOT, constants_1.COLLECTION_CHECKPOINT);
exports.collectionVcsPath = path_1.default.join(process.env.TUTURE_PATH || process.cwd(), constants_1.TUTURE_VCS_ROOT, constants_1.COLLECTION_PATH);
function hasCollectionChangedSinceCheckpoint() {
if (!fs_extra_1.default.existsSync(exports.collectionCheckpoint)) {
return true;
}
return !fs_extra_1.default
.readFileSync(exports.collectionPath)
.equals(fs_extra_1.default.readFileSync(exports.collectionCheckpoint));
}
exports.hasCollectionChangedSinceCheckpoint = hasCollectionChangedSinceCheckpoint;
/**
* Whether the local tuture branch exists.
*/
async function hasLocalTutureBranch() {
return (await git_1.git.branchLocal()).all.includes(constants_1.TUTURE_BRANCH);
}
exports.hasLocalTutureBranch = hasLocalTutureBranch;
/**
* Whether the remote tuture branch exists.
*/
async function hasRemoteTutureBranch() {
const remote = await git_1.git.remote([]);
if (!remote) {
logger_1.default.log('warning', 'No remote found for this repository.');
return false;
}
const branchExists = async (branch) => {
const { all } = await git_1.git.branch({ '-a': true });
return all.includes(remoteBranch);
};
const remoteBranch = `remotes/${remote.trim()}/${constants_1.TUTURE_BRANCH}`;
// Trying to update remote branches (time-consuming).
await git_1.git.remote(['update', '--prune']);
return await branchExists(remoteBranch);
}
exports.hasRemoteTutureBranch = hasRemoteTutureBranch;
/**
* Load collection.
*/
function loadCollection() {
let rawCollection = fs_extra_1.default.readFileSync(exports.collectionPath).toString();
const assetsTable = assets_1.loadAssetsTable();
// COMPAT: convert all asset paths
assetsTable.forEach((asset) => {
const { localPath, hostingUri } = asset;
if (hostingUri) {
rawCollection = rawCollection.replace(new RegExp(localPath, 'g'), hostingUri);
}
});
const collection = JSON.parse(rawCollection);
// COMPAT: convert hiddenLines field
if (collection.version !== 'v1') {
const convertHiddenLines = (hiddenLines) => {
const rangeGroups = [];
let startNumber = null;
for (let i = 0; i < hiddenLines.length; i++) {
const prev = hiddenLines[i - 1];
const current = hiddenLines[i];
const next = hiddenLines[i + 1];
if (current !== prev + 1 && current !== next - 1) {
rangeGroups.push([current, current]);
}
else if (current !== prev + 1) {
startNumber = hiddenLines[i];
}
else if (current + 1 !== next) {
rangeGroups.push([startNumber, hiddenLines[i]]);
}
}
return rangeGroups;
};
for (const step of collection.steps) {
for (const node of step.children) {
if (node.type === 'file') {
const diffBlock = node.children[1];
if (diffBlock.hiddenLines) {
diffBlock.hiddenLines = convertHiddenLines(diffBlock.hiddenLines);
}
}
}
}
collection.version = 'v1';
}
// COMPAT: normalize children of all diff blocks
for (const step of collection.steps) {
for (const node of step.children) {
if (node.type === 'file') {
const diffBlock = node.children[1];
diffBlock.children = [{ text: '' }];
}
}
}
return collection;
}
exports.loadCollection = loadCollection;
/**
* Save the entire collection back to workspace.
*/
function saveCollection(collection) {
fs_extra_1.default.writeFileSync(exports.collectionPath, JSON.stringify(collection, null, 2));
}
exports.saveCollection = saveCollection;
/**
* Fetch tuture branch from remote.
*/
async function initializeTutureBranch() {
const { all: allBranches } = await git_1.git.branch({ '-a': true });
// Already exists.
if (allBranches.includes(constants_1.TUTURE_BRANCH)) {
return;
}
const remoteBranchIndex = allBranches
.map((branch) => branch.split('/').slice(-1)[0])
.indexOf(constants_1.TUTURE_BRANCH);
if (remoteBranchIndex < 0) {
await git_1.git.branch([constants_1.TUTURE_BRANCH]);
logger_1.default.log('info', 'New tuture branch has been created.');
}
else {
const [_, remote, branch] = allBranches[remoteBranchIndex].split('/');
await git_1.git.fetch(remote, branch);
logger_1.default.log('success', 'Remote tuture branch has been fetched.');
}
}
exports.initializeTutureBranch = initializeTutureBranch;
function saveCheckpoint() {
// Copy the last committed file.
fs_extra_1.default.copySync(exports.collectionPath, exports.collectionCheckpoint, { overwrite: true });
}
exports.saveCheckpoint = saveCheckpoint;