-
Notifications
You must be signed in to change notification settings - Fork 698
Expand file tree
/
Copy pathreference.js
More file actions
213 lines (194 loc) · 5.63 KB
/
reference.js
File metadata and controls
213 lines (194 loc) · 5.63 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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
var util = require("util");
var NodeGit = require("../");
var LookupWrapper = NodeGit.Utils.lookupWrapper;
var Reference = NodeGit.Reference;
var Branch = NodeGit.Branch;
/**
* Retrieves the reference by it's short name
* @async
* @param {Repository} repo The repo that the reference lives in
* @param {String|Reference} id The reference to lookup
* @param {Function} callback
* @return {Reference}
*/
Reference.dwim = LookupWrapper(Reference, Reference.dwim);
/**
* Retrieves the reference pointed to by the oid
* @async
* @param {Repository} repo The repo that the reference lives in
* @param {String|Reference} id The reference to lookup
* @param {Function} callback
* @return {Reference}
*/
Reference.lookup = LookupWrapper(Reference);
/**
* Returns true if this reference is not symbolic
* @return {Boolean}
*/
Reference.prototype.isConcrete = function() {
return this.type() == Reference.TYPE.DIRECT;
};
/**
* Returns if the ref is pointed at by HEAD
* @return {Boolean}
*/
Reference.prototype.isHead = function() {
return Branch.isHead(this);
};
/**
* Returns true if this reference is symbolic
* @return {Boolean}
*/
Reference.prototype.isSymbolic = function() {
return this.type() == Reference.TYPE.SYMBOLIC;
};
/**
* Returns true if this reference is valid
* @return {Boolean}
*/
Reference.prototype.isValid = function() {
return this.type() != Reference.TYPE.INVALID;
};
/**
* Returns the name of the reference.
* @return {String}
*/
Reference.prototype.toString = function() {
return this.name();
};
const getTerminal = (repo, refName, depth = 10, prevRef = null) => {
if (depth <= 0) {
return Promise.resolve({
error: NodeGit.Error.CODE.ENOTFOUND,
out: prevRef
});
}
return NodeGit.Reference.lookup(repo, refName)
.then((ref) => {
if (ref.type() === NodeGit.Reference.TYPE.DIRECT) {
return {
error: NodeGit.Error.CODE.OK,
out: ref
};
} else {
return getTerminal(repo, ref.symbolicTarget(), depth - 1, ref)
.then(({ error, out }) => {
if (error === NodeGit.Error.CODE.ENOTFOUND && !out) {
return { error, out: ref };
} else {
return { error, out };
}
});
}
})
.catch((error) => {
return {
error: error.errno,
out: null
};
});
};
const getSignatureForReflog = (repo) => {
const { email, name } = repo.ident();
if (email && name) {
return Promise.resolve(NodeGit.Signature.now(name, email));
}
return NodeGit.Signature.default(repo)
.catch(() => NodeGit.Signature.now("unknown", "unknown"));
};
/**
* Given a reference name, follows symbolic links and updates the direct
* reference to point to a given OID. Updates the reflog with a given message.
*
* @async
* @param {Repository} repo The repo where the reference and objects live
* @param {String} refName The reference name to update
* @param {Oid} oid The target OID that the reference will point to
* @param {String} logMessage The reflog message to be writted
* @param {Signature} signature Optional signature to use for the reflog entry
*/
Reference.updateTerminal = function (
repo,
refName,
oid,
logMessage,
signature
) {
let signatureToUse;
let promiseChain = Promise.resolve();
if (!signature) {
promiseChain = promiseChain
.then(() => getSignatureForReflog(repo))
.then((sig) => {
signatureToUse = sig;
return Promise.resolve();
});
} else {
signatureToUse = signature;
}
return promiseChain
.then(() => getTerminal(repo, refName))
.then(({ error, out }) => {
if (error === NodeGit.Error.CODE.ENOTFOUND && out) {
return NodeGit.Reference.create(
repo,
out.symbolicTarget(),
oid,
0,
logMessage
);
} else if (error === NodeGit.Error.CODE.ENOTFOUND) {
return NodeGit.Reference.create(
repo,
refName,
oid,
0,
logMessage
);
} else {
return NodeGit.Reference.createMatching(
repo,
out.name(),
oid,
1,
out.target(),
logMessage
);
}
})
.then(() => NodeGit.Reflog.read(repo, refName))
.then((reflog) => {
// Janky, but works. Ideally, we would want to generate the correct reflog
// entry in the first place, rather than drop the most recent entry and
// write the correct one.
// NOTE: There is a theoretical race condition that could happen here.
// We may want to consider some kind of transactional logic to make sure
// that the reflog on disk isn't modified before we can write back.
reflog.drop(0, 1);
reflog.append(oid, signatureToUse, logMessage);
return reflog.write();
});
};
// Deprecated -----------------------------------------------------------------
Object.defineProperty(NodeGit.Reference.TYPE, "OID", {
get: util.deprecate(
() => NodeGit.Reference.TYPE.DIRECT,
"Use NodeGit.Reference.TYPE.DIRECT instead of NodeGit.Reference.TYPE.OID."
)
});
Object.defineProperty(NodeGit.Reference.TYPE, "LISTALL", {
get: util.deprecate(
() => NodeGit.Reference.TYPE.ALL,
"Use NodeGit.Reference.TYPE.ALL instead of NodeGit.Reference.TYPE.LISTALL."
)
});
NodeGit.Reference.NORMALIZE = {};
Object.keys(NodeGit.Reference.FORMAT).forEach((key) => {
Object.defineProperty(NodeGit.Reference.NORMALIZE, `REF_FORMAT_${key}`, {
get: util.deprecate(
() => NodeGit.Reference.FORMAT[key],
`Use NodeGit.Reference.FORMAT.${key} instead of ` +
`NodeGit.Reference.NORMALIZE.REF_FORMAT_${key}.`
)
});
});