Skip to content

Commit

Permalink
fix: --no-squash on single-commit GitLab MR (#93)
Browse files Browse the repository at this point in the history
Due to off-by-one error in GitLabMapper, --no-squash was not effective
on an MR containing single commit. Fix by using the same condition as
GitHubMapper.
  • Loading branch information
peat-psuwit committed Feb 20, 2024
1 parent b7df1f8 commit 300fa91
Show file tree
Hide file tree
Showing 7 changed files with 376 additions and 165 deletions.
212 changes: 131 additions & 81 deletions dist/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1165,8 +1165,8 @@ class GitLabMapper {
sourceRepo: await this.mapSourceRepo(mr),
targetRepo: await this.mapTargetRepo(mr),
// if commits list is provided use that as source
nCommits: (commits && commits.length > 1) ? commits.length : 1,
commits: (commits && commits.length > 1) ? commits : this.getSha(mr)
nCommits: (commits && commits.length > 0) ? commits.length : 1,
commits: (commits && commits.length > 0) ? commits : this.getSha(mr)
};
}
getSha(mr) {
Expand Down Expand Up @@ -5847,6 +5847,29 @@ var Writable = (__nccwpck_require__(2781).Writable);
var assert = __nccwpck_require__(9491);
var debug = __nccwpck_require__(1133);

// Whether to use the native URL object or the legacy url module
var useNativeURL = false;
try {
assert(new URL());
}
catch (error) {
useNativeURL = error.code === "ERR_INVALID_URL";
}

// URL fields to preserve in copy operations
var preservedUrlFields = [
"auth",
"host",
"hostname",
"href",
"path",
"pathname",
"port",
"protocol",
"query",
"search",
];

// Create handlers that pass events from native requests
var events = ["abort", "aborted", "connect", "error", "socket", "timeout"];
var eventHandlers = Object.create(null);
Expand All @@ -5856,19 +5879,20 @@ events.forEach(function (event) {
};
});

// Error types with codes
var InvalidUrlError = createErrorType(
"ERR_INVALID_URL",
"Invalid URL",
TypeError
);
// Error types with codes
var RedirectionError = createErrorType(
"ERR_FR_REDIRECTION_FAILURE",
"Redirected request failed"
);
var TooManyRedirectsError = createErrorType(
"ERR_FR_TOO_MANY_REDIRECTS",
"Maximum number of redirects exceeded"
"Maximum number of redirects exceeded",
RedirectionError
);
var MaxBodyLengthExceededError = createErrorType(
"ERR_FR_MAX_BODY_LENGTH_EXCEEDED",
Expand All @@ -5879,6 +5903,9 @@ var WriteAfterEndError = createErrorType(
"write after end"
);

// istanbul ignore next
var destroy = Writable.prototype.destroy || noop;

// An HTTP(S) request that can be redirected
function RedirectableRequest(options, responseCallback) {
// Initialize the request
Expand All @@ -5900,7 +5927,13 @@ function RedirectableRequest(options, responseCallback) {
// React to responses of native requests
var self = this;
this._onNativeResponse = function (response) {
self._processResponse(response);
try {
self._processResponse(response);
}
catch (cause) {
self.emit("error", cause instanceof RedirectionError ?
cause : new RedirectionError({ cause: cause }));
}
};

// Perform the first request
Expand All @@ -5909,10 +5942,17 @@ function RedirectableRequest(options, responseCallback) {
RedirectableRequest.prototype = Object.create(Writable.prototype);

RedirectableRequest.prototype.abort = function () {
abortRequest(this._currentRequest);
destroyRequest(this._currentRequest);
this._currentRequest.abort();
this.emit("abort");
};

RedirectableRequest.prototype.destroy = function (error) {
destroyRequest(this._currentRequest, error);
destroy.call(this, error);
return this;
};

// Writes buffered data to the current native request
RedirectableRequest.prototype.write = function (data, encoding, callback) {
// Writing is not allowed if end has been called
Expand Down Expand Up @@ -6025,6 +6065,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
self.removeListener("abort", clearTimer);
self.removeListener("error", clearTimer);
self.removeListener("response", clearTimer);
self.removeListener("close", clearTimer);
if (callback) {
self.removeListener("timeout", callback);
}
Expand All @@ -6051,6 +6092,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
this.on("abort", clearTimer);
this.on("error", clearTimer);
this.on("response", clearTimer);
this.on("close", clearTimer);

return this;
};
Expand Down Expand Up @@ -6109,8 +6151,7 @@ RedirectableRequest.prototype._performRequest = function () {
var protocol = this._options.protocol;
var nativeProtocol = this._options.nativeProtocols[protocol];
if (!nativeProtocol) {
this.emit("error", new TypeError("Unsupported protocol " + protocol));
return;
throw new TypeError("Unsupported protocol " + protocol);
}

// If specified, use the agent corresponding to the protocol
Expand Down Expand Up @@ -6202,15 +6243,14 @@ RedirectableRequest.prototype._processResponse = function (response) {
}

// The response is a redirect, so abort the current request
abortRequest(this._currentRequest);
destroyRequest(this._currentRequest);
// Discard the remainder of the response to avoid waiting for data
response.destroy();

// RFC7231§6.4: A client SHOULD detect and intervene
// in cyclical redirections (i.e., "infinite" redirection loops).
if (++this._redirectCount > this._options.maxRedirects) {
this.emit("error", new TooManyRedirectsError());
return;
throw new TooManyRedirectsError();
}

// Store the request headers if applicable
Expand Down Expand Up @@ -6244,33 +6284,23 @@ RedirectableRequest.prototype._processResponse = function (response) {
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);

// If the redirect is relative, carry over the host of the last request
var currentUrlParts = url.parse(this._currentUrl);
var currentUrlParts = parseUrl(this._currentUrl);
var currentHost = currentHostHeader || currentUrlParts.host;
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
url.format(Object.assign(currentUrlParts, { host: currentHost }));

// Determine the URL of the redirection
var redirectUrl;
try {
redirectUrl = url.resolve(currentUrl, location);
}
catch (cause) {
this.emit("error", new RedirectionError({ cause: cause }));
return;
}

// Create the redirected request
debug("redirecting to", redirectUrl);
var redirectUrl = resolveUrl(location, currentUrl);
debug("redirecting to", redirectUrl.href);
this._isRedirect = true;
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);
spreadUrlObject(redirectUrl, this._options);

// Drop confidential headers when redirecting to a less secure protocol
// or to a different domain that is not a superdomain
if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
redirectUrlParts.protocol !== "https:" ||
redirectUrlParts.host !== currentHost &&
!isSubdomain(redirectUrlParts.host, currentHost)) {
if (redirectUrl.protocol !== currentUrlParts.protocol &&
redirectUrl.protocol !== "https:" ||
redirectUrl.host !== currentHost &&
!isSubdomain(redirectUrl.host, currentHost)) {
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
}

Expand All @@ -6285,23 +6315,12 @@ RedirectableRequest.prototype._processResponse = function (response) {
method: method,
headers: requestHeaders,
};
try {
beforeRedirect(this._options, responseDetails, requestDetails);
}
catch (err) {
this.emit("error", err);
return;
}
beforeRedirect(this._options, responseDetails, requestDetails);
this._sanitizeOptions(this._options);
}

// Perform the redirected request
try {
this._performRequest();
}
catch (cause) {
this.emit("error", new RedirectionError({ cause: cause }));
}
this._performRequest();
};

// Wraps the key/value object of protocols with redirect functionality
Expand All @@ -6321,27 +6340,16 @@ function wrap(protocols) {

// Executes a request, following redirects
function request(input, options, callback) {
// Parse parameters
if (isString(input)) {
var parsed;
try {
parsed = urlToOptions(new URL(input));
}
catch (err) {
/* istanbul ignore next */
parsed = url.parse(input);
}
if (!isString(parsed.protocol)) {
throw new InvalidUrlError({ input });
}
input = parsed;
// Parse parameters, ensuring that input is an object
if (isURL(input)) {
input = spreadUrlObject(input);
}
else if (URL && (input instanceof URL)) {
input = urlToOptions(input);
else if (isString(input)) {
input = spreadUrlObject(parseUrl(input));
}
else {
callback = options;
options = input;
options = validateUrl(input);
input = { protocol: protocol };
}
if (isFunction(options)) {
Expand Down Expand Up @@ -6380,27 +6388,57 @@ function wrap(protocols) {
return exports;
}

/* istanbul ignore next */
function noop() { /* empty */ }

// from https://github.com/nodejs/node/blob/master/lib/internal/url.js
function urlToOptions(urlObject) {
var options = {
protocol: urlObject.protocol,
hostname: urlObject.hostname.startsWith("[") ?
/* istanbul ignore next */
urlObject.hostname.slice(1, -1) :
urlObject.hostname,
hash: urlObject.hash,
search: urlObject.search,
pathname: urlObject.pathname,
path: urlObject.pathname + urlObject.search,
href: urlObject.href,
};
if (urlObject.port !== "") {
options.port = Number(urlObject.port);
function parseUrl(input) {
var parsed;
/* istanbul ignore else */
if (useNativeURL) {
parsed = new URL(input);
}
else {
// Ensure the URL is valid and absolute
parsed = validateUrl(url.parse(input));
if (!isString(parsed.protocol)) {
throw new InvalidUrlError({ input });
}
}
return parsed;
}

function resolveUrl(relative, base) {
/* istanbul ignore next */
return useNativeURL ? new URL(relative, base) : parseUrl(url.resolve(base, relative));
}

function validateUrl(input) {
if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
throw new InvalidUrlError({ input: input.href || input });
}
if (/^\[/.test(input.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input.host)) {
throw new InvalidUrlError({ input: input.href || input });
}
return options;
return input;
}

function spreadUrlObject(urlObject, target) {
var spread = target || {};
for (var key of preservedUrlFields) {
spread[key] = urlObject[key];
}

// Fix IPv6 hostname
if (spread.hostname.startsWith("[")) {
spread.hostname = spread.hostname.slice(1, -1);
}
// Ensure port is a number
if (spread.port !== "") {
spread.port = Number(spread.port);
}
// Concatenate path
spread.path = spread.search ? spread.pathname + spread.search : spread.pathname;

return spread;
}

function removeMatchingHeaders(regex, headers) {
Expand All @@ -6426,17 +6464,25 @@ function createErrorType(code, message, baseClass) {

// Attach constructor and set default properties
CustomError.prototype = new (baseClass || Error)();
CustomError.prototype.constructor = CustomError;
CustomError.prototype.name = "Error [" + code + "]";
Object.defineProperties(CustomError.prototype, {
constructor: {
value: CustomError,
enumerable: false,
},
name: {
value: "Error [" + code + "]",
enumerable: false,
},
});
return CustomError;
}

function abortRequest(request) {
function destroyRequest(request, error) {
for (var event of events) {
request.removeListener(event, eventHandlers[event]);
}
request.on("error", noop);
request.abort();
request.destroy(error);
}

function isSubdomain(subdomain, domain) {
Expand All @@ -6457,6 +6503,10 @@ function isBuffer(value) {
return typeof value === "object" && ("length" in value);
}

function isURL(value) {
return URL && value instanceof URL;
}

// Exports
module.exports = wrap({ http: http, https: https });
module.exports.wrap = wrap;
Expand Down

0 comments on commit 300fa91

Please sign in to comment.