Skip to content

Commit

Permalink
tool to add redirects (#1510)
Browse files Browse the repository at this point in the history
* Tool to add redirects

Part of #1418

* progress

* conslidate move/remove

* add document move / delete to cli

* tooling: default to en-US

* use git to move files around

* work on document edit / create

* fix github action

* default to yes for cli tool

* fix non git content root

* add more commands to cli

* add description to commands

* Error handling when moving slugs + verbose level.

* fix redirect add

* rename import

* move to dash separated commands

* Update tool/cli.js

Co-authored-by: Peter Bengtsson <[email protected]>

* remove redirects from scripts (replaced with tool)

* fix yarn

Co-authored-by: Peter Bengtsson <[email protected]>
Co-authored-by: Peter Bengtsson <[email protected]>
  • Loading branch information
3 people authored Oct 27, 2020
1 parent c8d4dac commit d346733
Show file tree
Hide file tree
Showing 11 changed files with 497 additions and 110 deletions.
2 changes: 1 addition & 1 deletion build/flaws.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ async function fixFixableFlaws(doc, options, document) {
)
);
} else {
Document.update(document.fileInfo.folder, newRawHTML, document.metadata);
Document.update(document.url, newRawHTML, document.metadata);
if (options.fixFlawsVerbose) {
console.log(
chalk.green(
Expand Down
28 changes: 15 additions & 13 deletions build/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
const childProcess = require("child_process");

const chalk = require("chalk");

const { Document, CONTENT_ROOT, REPOSITORY_URLS } = require("../content");
const {
Document,
CONTENT_ROOT,
REPOSITORY_URLS,
execGit,
} = require("../content");
const kumascript = require("../kumascript");

const { FLAW_LEVELS } = require("./constants");
Expand Down Expand Up @@ -35,23 +38,22 @@ function getCurrentGitBranch(root) {
// Only bother getting fancy if the root is CONTENT_ROOT.
// For other possible roots, just leave it to the default.
if (root === CONTENT_ROOT) {
if (process.env.GITHUB_REF_NAME_SLUG) {
name = process.env.GITHUB_REF_NAME_SLUG;
if (process.env.GITHUB_REF) {
name = process.env.GITHUB_REF.split("/").slice(2).join("/");
} else {
// Most probably, you're hacking on the content, using Yari to preview,
// in a topic branch. Then figure this out using a child-process.
// Note, if you're in detached head, (e.g. "d6a6c3f17") instead of a named
// branch, this will fail. But that's why we rely on a default.
const spawned = childProcess.spawnSync(
"git",
["branch", "--show-current"],
{
try {
const output = execGit(["branch", "--show-current"], {
cwd: root,
});
if (output) {
name = output;
}
);
const output = spawned.stdout.toString().trim();
if (output) {
name = output;
} catch (e) {
/* allowed to fail for non git content root */
}
}
}
Expand Down
141 changes: 123 additions & 18 deletions content/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const {
const { getPopularities } = require("./popularities");
const { getWikiHistories } = require("./wikihistories");

const { memoize, slugToFolder } = require("./utils");
const { buildURL, memoize, slugToFolder, execGit } = require("./utils");
const Redirect = require("./redirect");

function buildPath(localeFolder, slug) {
return path.join(localeFolder, slugToFolder(slug));
Expand Down Expand Up @@ -194,8 +195,9 @@ const read = memoize((folder) => {
};
});

function update(folder, rawHTML, metadata) {
const folderPath = path.join(CONTENT_ROOT, getHTMLPath(folder));
function update(url, rawHTML, metadata) {
const folder = urlToFolderPath(url);
const indexPath = path.join(CONTENT_ROOT, getHTMLPath(folder));
const document = read(folder);
const oldSlug = document.metadata.slug;
const newSlug = metadata.slug;
Expand All @@ -206,7 +208,7 @@ function update(folder, rawHTML, metadata) {
document.rawHTML !== rawHTML ||
document.metadata.title !== metadata.title
) {
saveHTMLFile(folderPath, rawHTML, {
saveHTMLFile(indexPath, rawHTML, {
...document.metadata,
...metadata,
});
Expand All @@ -220,7 +222,11 @@ function update(folder, rawHTML, metadata) {
}

if (isNewSlug) {
const locale = metadata.locale;
const redirects = new Map();
const url = buildURL(locale, oldSlug);
for (const { metadata, rawHTML, fileInfo } of findChildren(url)) {
const childLocale = metadata.locale;
const oldChildSlug = metadata.slug;
const newChildSlug = oldChildSlug.replace(oldSlug, newSlug);
metadata.slug = newChildSlug;
Expand All @@ -230,25 +236,26 @@ function update(folder, rawHTML, metadata) {
newChildSlug
);
saveHTMLFile(fileInfo.path, rawHTML, metadata);
redirects.set(
buildURL(childLocale, oldChildSlug),
buildURL(childLocale, newChildSlug)
);
}
redirects.set(buildURL(locale, oldSlug), buildURL(locale, newSlug));
const newFolderPath = buildPath(
path.join(CONTENT_ROOT, metadata.locale.toLowerCase()),
path.join(CONTENT_ROOT, locale.toLowerCase()),
newSlug
);
const oldFolderPath = buildPath(
path.join(CONTENT_ROOT, locale.toLowerCase()),
oldSlug
);

// XXX we *could* call out to a shell here and attempt
// to execute `git mv $folder $newFolder` and only if that didn't work
// do we fall back on good old `fs.renameSync`.
fs.renameSync(folderPath, newFolderPath);
execGit(["mv", oldFolderPath, newFolderPath]);
Redirect.add(locale, [...redirects.entries()]);
}
}

function del(folder) {
const { metadata, fileInfo } = read(folder);
fs.rmdirSync(path.dirname(fileInfo.path), { recursive: true });
updateWikiHistory(path.join(CONTENT_ROOT, metadata.locale), metadata.slug);
}

function findByURL(url, ...args) {
const [bareURL, hash = ""] = url.split("#", 2);
const doc = read(urlToFolderPath(bareURL), ...args);
Expand All @@ -261,7 +268,7 @@ function findByURL(url, ...args) {
function findAll(
{ files, folderSearch } = { files: new Set(), folderSearch: null }
) {
if (!files instanceof Set) throw new TypeError("'files' not a Set");
if (!(files instanceof Set)) throw new TypeError("'files' not a Set");
if (folderSearch && typeof folderSearch !== "string")
throw new TypeError("'folderSearch' not a string");

Expand Down Expand Up @@ -291,7 +298,7 @@ function findAll(
if (files.has(filePath)) {
return true;
}
for (fp of files) {
for (const fp of files) {
if (filePath.endsWith(fp)) {
return true;
}
Expand Down Expand Up @@ -333,14 +340,112 @@ function findChildren(url) {
.map((folder) => read(folder));
}

function move(oldSlug, newSlug, locale, { dry = false } = {}) {
const oldUrl = buildURL(locale, oldSlug);
const doc = findByURL(oldUrl);
if (!doc) {
throw new Error(`document for ${oldSlug} does not exist`);
}
const realOldSlug = doc.metadata.slug;
const paris = [doc, ...findChildren(oldUrl)].map(({ metadata }) => [
metadata.slug,
metadata.slug.replace(realOldSlug, newSlug),
]);
if (dry) {
return paris;
}

doc.metadata.slug = newSlug;
update(oldUrl, doc.rawHTML, doc.metadata);

return paris;
}

function fileForSlug(slug, locale) {
return getHTMLPath(getFolderPath({ slug, locale }));
}

function exists(slug, locale) {
return Boolean(read(buildPath(locale.toLowerCase(), slug)));
}

function parentSlug(slug) {
return slug.split("/").slice(0, -1).join("/");
}

function validate(slug, locale) {
const errors = [];
const file = buildPath(locale.toLowerCase(), slug);

const doc = read(file);

if (doc.metadata.slug.toLowerCase() !== slug.toLowerCase()) {
errors.push("slug mismatch");
}
// Add more validations here.

if (errors.length > 0) {
throw new Error(errors.join(", "));
}
}

function remove(
slug,
locale,
{ recursive = false, dry = false, redirect = "" } = {}
) {
const url = buildURL(locale, slug);
const { metadata, fileInfo } = findByURL(url) || {};
if (!metadata) {
throw new Error(`document does not exists: ${url}`);
}

const children = findChildren(url);
if (children.length > 0 && (redirect || !recursive)) {
throw new Error("unable to remove and redirect a document with children");
}
const docs = [slug, ...children.map(({ metadata }) => metadata.slug)];

if (dry) {
return docs;
}

for (const { metadata } of children) {
const slug = metadata.slug;
updateWikiHistory(
path.join(CONTENT_ROOT, metadata.locale.toLowerCase()),
slug
);
}

if (redirect) {
Redirect.add(locale, [[url, redirect]]);
}

execGit(["rm", "-r", path.dirname(fileInfo.path)]);

updateWikiHistory(
path.join(CONTENT_ROOT, metadata.locale.toLowerCase()),
metadata.slug
);

return docs;
}

module.exports = {
create,
archive,
read,
update,
del,
exists,
remove,
move,
validate,

urlToFolderPath,
getFolderPath,
fileForSlug,
parentSlug,

findByURL,
findAll,
Expand Down
3 changes: 2 additions & 1 deletion content/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Document = require("./document");
const { getPopularities } = require("./popularities");
const Redirect = require("./redirect");
const Image = require("./image");
const { buildURL, memoize, slugToFolder } = require("./utils");
const { buildURL, memoize, slugToFolder, execGit } = require("./utils");
const { resolveFundamental } = require("@yari-internal/fundamental-redirects");

module.exports = {
Expand All @@ -31,4 +31,5 @@ module.exports = {
memoize,
slugToFolder,
resolveFundamental,
execGit,
};
Loading

0 comments on commit d346733

Please sign in to comment.