This repository was archived by the owner on Mar 22, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathsync.js
More file actions
180 lines (138 loc) · 5.88 KB
/
Copy pathsync.js
File metadata and controls
180 lines (138 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
const config = require("../config");
const debug = require('debug')('lib:sync');
const Octokit = require('@octokit/rest');
const updateLocalRepo = require('../lib/updateLocalRepo');
const run = require('../lib/run');
const path = require('path');
const octokitBot = new Octokit({
auth: `token ${config.secret.github.tokenBot}`,
// log: console
});
module.exports = async (langInfo) => {
await updateLocalRepo(langInfo.code);
let translatedPath = path.join(config.repoRoot, `${langInfo.code}.${config.repoSuffix}`);
await run(`git fetch upstream master`, { cwd: translatedPath });
const hash = await run(`git rev-parse upstream/master`, { cwd: translatedPath });
const shortHash = hash.slice(0, 8);
const syncBranch = `sync-${shortHash}`;
await run(`git checkout -B ${syncBranch} master`, {cwd: translatedPath});
// Pull from {source}/master
let output;
try {
output = await run(`git pull upstream master`, {cwd: translatedPath});
} catch(err) {
if (err.code === 1 && err.stdout.trim().endsWith('Automatic merge failed; fix conflicts and then commit the result.')) {
// merge failed, let's handle the output
output = err.stdout;
} else {
throw err;
}
}
if (output.includes('Already up to date.')) {
debug(`We are already up to date with upstream`);
return;
}
let conflictFiles = await run(`git diff --name-only --diff-filter=U`, {cwd: translatedPath });
conflictFiles = conflictFiles.split('\n');
// if (conflictFiles[0] === 'Readme.md' && conflictFiles.length === 1) {
// await run(`git checkout --ours Readme.md`, {cwd: translatedPath });
// await run(`git commit -m 'readme only' Readme.md`, {cwd: translatedPath });
// }
if (conflictFiles[0] === '') conflictFiles.shift(); // if no conflicts, conflictFiles becomes ['']
if (conflictFiles.length) {
await run(`git commit -am "merging all conflicts"`, {cwd: translatedPath});
} else {
// If no conflicts, merge directly into master
debug('No conflicts found. Committing directly to master.');
await run(`git checkout master`, {cwd: translatedPath});
await run(`git merge ${syncBranch}`, {cwd: translatedPath});
await run(`git push origin master`, {cwd: translatedPath});
debug("master updated, done");
return;
}
debug('conflict files: ', conflictFiles.join('\n'));
// Create a new pull request, listing all conflicting files
await run(`git push --force --set-upstream origin ${syncBranch}`, {cwd: translatedPath});
const title = `Sync with upstream @ ${shortHash}`;
let conflictList = conflictFiles.map(
file => `- [ ] [${file}](/${config.org}/${config.langMain}.${config.repoSuffix}/commits/master/${file})`
).join('\n');
if (conflictFiles.length > 20) {
conflictList = `<details><summary>Click to open a list of ${conflictFiles.length} files</summary>\n\n${conflictList}\n</details>`;
}
const readmeTip = conflictFiles.map(f => f.toLowerCase()).includes('readme.md') ? '\nPlease ignore changes in Readme.md (git checkout --ours Readme.md && git commit -m ignore Readme.md).\n' : '';
if (conflictList) {
conflictList = `
The following files have conflicts and may need new translations:
${conflictList}
Please fix the conflicts by pushing new commits to this pull request, either by editing the files directly on GitHub or by checking out this branch.
`;
} else {
conflictList = 'No conflicts were found.';
}
let tips = '';
if (conflictList) {
tips = `
We recommend to close this PR and merge conflicting changes manually.
The steps are:
1. Add remote upstream that links to the English version (only needs to be done once)
- \`git add remote upstream https://github.com/javascript-tutorial/en.javascript.info\`
2. Commit all current work locally and \`git checkout master\`
3. Pull the recent changes from the English version:
- \`git pull upstream master\`
4. Deal with the conflicts. If a conflict touches a few lines, then just fix them. Otherwise, following commands can help:
- Checkout translated version of a file/folder at the given path:
- \`git checkout --ours <path>\`
- Checkout upstream version of a file/folder at the given path:
- \`git checkout --theirs <path>\`
- See what changed in the upstream file since branches diverged:
- \`git diff --word-diff master...upstream/master <path>\` (please note: three dots in the command)
5. When conflicts resolved, commit them and \`git push origin master\`
${readmeTip}
`;
}
const body = `
This PR was automatically generated.
Merge changes from [en.javascript.info](https://github.com/${config.org}/${config.langMain}.${config.repoSuffix}/commits/master) at ${shortHash}
${conflictList}
${tips}
`;
try {
debug("Look for sync PRs");
let existingPrs = await octokitBot.search.issuesAndPullRequests({
q: `type:pr Sync with upstream in:title is:open author:${config.botUser} repo:${config.org}/${langInfo.code}.${config.repoSuffix}`
});
for(let existingPr of existingPrs.data.items) {
debug("Delete PR " + existingPr.number);
await octokitBot.pulls.update({
owner: config.org,
repo: `${langInfo.code}.${config.repoSuffix}`,
pull_number: existingPr.number,
state: 'closed'
});
}
debug("Create sync PR");
const { data: {number: pull_number} } = await octokitBot.pulls.create({
owner: config.org,
repo: `${langInfo.code}.${config.repoSuffix}`,
title,
body,
head: syncBranch,
base: 'master',
});
// adding reviewers doesn't work, error:
// Could not add requested reviewers to pull request.
/*
await octokitBot.pulls.createReviewRequest({
owner: config.org,
repo: `${langInfo.code}.${config.repoSuffix}`,
pull_number,
reviewers: [langInfo.maintainers[0]]
});*/
} catch(err) {
if (err.name === 'HttpError') {
console.error(err.errors);
}
throw err;
}
};