forked from stevetweeddale/gatsby-source-git
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gatsby-node.js
115 lines (103 loc) · 3.27 KB
/
gatsby-node.js
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
const Git = require("simple-git/promise");
const fastGlob = require("fast-glob");
const fs = require("fs");
const { createFileNode } = require("gatsby-source-filesystem/create-file-node");
const GitUrlParse = require("git-url-parse");
async function isAlreadyCloned(remote, path) {
const existingRemote = await Git(path).listRemote(["--get-url"]);
return existingRemote.trim() == remote.trim();
}
async function getTargetBranch(repo, branch) {
if (typeof branch == `string`) {
return `origin/${branch}`;
} else {
return repo.raw(["symbolic-ref", "--short", "refs/remotes/origin/HEAD"]).then(result => result.trim());
}
}
async function getRepo(path, remote, branch) {
// If the directory doesn't exist or is empty, clone. This will be the case if
// our config has changed because Gatsby trashes the cache dir automatically
// in that case.
if (!fs.existsSync(path) || fs.readdirSync(path).length === 0) {
let opts = [`--depth`, `1`];
if (typeof branch == `string`) {
opts.push(`--branch`, branch);
}
await Git().clone(remote, path, opts);
return Git(path);
} else if (await isAlreadyCloned(remote, path)) {
const repo = await Git(path);
const target = await getTargetBranch(repo, branch);
// Refresh our shallow clone with the latest commit.
await repo
.fetch([`--depth`, `1`])
.then(() => repo.reset([`--hard`, target]));
return repo;
} else {
throw new Error(`Can't clone to target destination: ${localPath}`);
}
}
exports.sourceNodes = async (
{
actions: { createNode },
store,
createNodeId,
createContentDigest,
reporter
},
{ name, remote, branch, patterns = `**`, local }
) => {
const programDir = store.getState().program.directory;
const localPath = local || require("path").join(
programDir,
`.cache`,
`gatsby-source-git`,
name
);
const parsedRemote = GitUrlParse(remote);
let repo;
try {
repo = await getRepo(localPath, remote, branch);
} catch (e) {
return reporter.error(e);
}
parsedRemote.git_suffix = false;
parsedRemote.webLink = parsedRemote.toString("https");
delete parsedRemote.git_suffix;
let ref = await repo.raw(["rev-parse", "--abbrev-ref", "HEAD"]);
parsedRemote.ref = ref.trim();
const repoFiles = await fastGlob(patterns, {
cwd: localPath,
absolute: true
});
const remoteId = createNodeId(`git-remote-${name}`);
// Create a single graph node for this git remote.
// Filenodes sourced from it will get a field pointing back to it.
await createNode(
Object.assign(parsedRemote, {
id: remoteId,
sourceInstanceName: name,
parent: null,
children: [],
internal: {
type: `GitRemote`,
content: JSON.stringify(parsedRemote),
contentDigest: createContentDigest(parsedRemote)
}
})
);
const createAndProcessNode = path => {
return createFileNode(path, createNodeId, {
name: name,
path: localPath
}).then(fileNode => {
// Add a link to the git remote node
fileNode.gitRemote___NODE = remoteId;
// Then create the node, as if it were created by the gatsby-source
// filesystem plugin.
return createNode(fileNode);
});
};
return Promise.all(repoFiles.map(createAndProcessNode));
};
exports.onCreateNode;