mirror of https://github.com/lukechilds/node.git
Browse Source
PR-URL: https://github.com/nodejs/node/pull/12480 Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>v6
Rebecca Turner
8 years ago
committed by
Jeremiah Senkpiel
1229 changed files with 67108 additions and 31294 deletions
@ -1,12 +1,82 @@ |
|||||
## Before you submit a new issue |
# npm CLI Contributor Roles and Responsibilities |
||||
|
|
||||
* Check if there's a simple solution in the |
## Table of Contents |
||||
[Troubleshooting](https://github.com/npm/npm/wiki/Troubleshooting) |
|
||||
wiki. |
* [Introduction](#introduction) |
||||
* [Search for similar |
* [Roles](#roles) |
||||
issues](https://github.com/npm/npm/search?q=Similar%20issues&type=Issues). |
* [Community Members](#community-members) |
||||
* Ensure your new issue conforms to the [Contributing |
* [Collaborators](#collaborators) |
||||
Guidelines](https://github.com/npm/npm/wiki/Contributing-Guidelines). |
* [npm, Inc Employeees](#npm-inc-employees) |
||||
|
|
||||
Participation in this open source project is subject to the [npm Code |
|
||||
of Conduct](http://www.npmjs.com/policies/conduct). |
## Introduction |
||||
|
|
||||
|
Welcome to the npm CLI Contributor Guide! This document outlines the npm CLI repository's process for community interaction and contribution. This includes the issue tracker, pull requests, wiki pages, and, to a certain extent, outside communication in the context of the npm CLI. It defines roles, responsibilities, and procedures, and is an entry point for anyone wishing to contribute their time and effort to making npm a better tool for the JavaScript community! |
||||
|
|
||||
|
All interactions in the npm repository are covered by the [npm Code of Conduct](https://www.npmjs.com/policies/conduct) |
||||
|
|
||||
|
## Roles |
||||
|
|
||||
|
There are three main roles for people participating in the npm issue tracker. Each has a specific set of abilities and responsibilities: [Community members](#community-members), [Collaborators](#collaborators), and [npm, Inc employees](#npm-inc-employees). |
||||
|
|
||||
|
Failure to comply with the expected responsibilities of each role, or violating the Code of Conduct will result in punitive action relative to the transgression, ranging from a warning to full removal from the project, at the discretion of npm employees. |
||||
|
|
||||
|
### Community Members |
||||
|
|
||||
|
This includes anyone who may show up to the npm/npm repo with issues, PRs, comments etc. They may not have any other involvement with npm. |
||||
|
|
||||
|
#### Abilities |
||||
|
|
||||
|
* Open issues and PRs |
||||
|
* Comment on issues and PRs |
||||
|
|
||||
|
#### Responsibilities |
||||
|
|
||||
|
* Comment on issues when they have a reference to the answer. |
||||
|
* If community members aren't sure they are correct and don't have a reference to the answer, please leave the issue and try another one. |
||||
|
* Defer to collaborators and npm employees for answers. |
||||
|
* Make sure to search for [the troubleshooting doc](./TROUBLESHOOTING.md) and search on the issue tracker for similar issues before opening a new one. |
||||
|
* Any users with urgent support needs are welcome to email support@npmjs.com, and our dedicated support team will be happy to help. |
||||
|
|
||||
|
PLEASE don't @ collaborators or npm employees on issues. The CLI team is small, and has many outstanding commitments to fulfill. |
||||
|
|
||||
|
### Collaborators |
||||
|
|
||||
|
These are folks who have the ability to label and close issues. The role of collaborators may expand over time, but for now it is a limited (& important) role. This is an excellent way to contribute to npm without writing code. |
||||
|
|
||||
|
Community members may become collaborators by showing consistent, proven track record of quality contributions to the project, a reasonable level of proficiency with the CLI, and regular participation through the tracker and other related mediums, including regular contact with the CLI team itself. This role entails a higher level of responsibility than community member, so we ask for a higher level of understanding and commitment. |
||||
|
|
||||
|
Collaborators who become inactive for 3 months or longer may have their collaborator privileges removed until they are ready to return. |
||||
|
|
||||
|
#### Abilities |
||||
|
|
||||
|
* Label/triage new issues |
||||
|
* Respond to ongoing issues |
||||
|
* Close resolved issues. |
||||
|
|
||||
|
#### Responsibilities |
||||
|
|
||||
|
* Only answer questions when they know the answer, and provide a reference to the answer. |
||||
|
* If collaborators aren't totally confident about their answer, please leave the issue and try another one. |
||||
|
* If they've responded to an issue, it becomes their responsibility to see it to resolution. |
||||
|
* Close issues if there's no response within a month. |
||||
|
* Defer to fellow Collaborators & npm employees for answers (Again, please don't @ collaborators or npm employees, thank you!) |
||||
|
* Make sure to search for [the troubleshooting doc](./TROUBLESHOOTING.md) and search on the issue tracker for similar issues before opening a new one. |
||||
|
|
||||
|
### npm, Inc Employees |
||||
|
|
||||
|
Folks who work at npm, Inc, who have a responsibility to ensure the stability and functionality of the tools npm offers. |
||||
|
|
||||
|
#### Abilities |
||||
|
* Label/triage new issues |
||||
|
* Respond to ongoing issues |
||||
|
* Close resolved issues |
||||
|
* Land PRs |
||||
|
|
||||
|
Please note that this is a living document, and the CLI team will put up PRs to it as needed. |
||||
|
|
||||
|
#### Responsibilities |
||||
|
|
||||
|
* Preserve and promote the health of the CLI, the registry, the website, etc. |
||||
|
|
||||
|
In special cases, [Collaborators](#collaborators) may request time to speak with an npm employee directly, by contacting them and coordinating a time/place. |
||||
|
@ -0,0 +1,192 @@ |
|||||
|
# Troubleshooting Common Issues |
||||
|
|
||||
|
## Using this Document |
||||
|
|
||||
|
Search for the error message you're getting and see if there's a match, or skim the [table of contents](#table-of-contents) below for topics that seem relevant to the issue you're having. Each issue section has steps to work around or fix the particular issue, and have examples of common error messages. |
||||
|
|
||||
|
If you do not find the issue below, try searching the issue tracker itself for potential duplicates before opening a new issue. |
||||
|
|
||||
|
If you're reading this document because you noticed an issue with npm's web site, please let the [web team](https://github.com/npm/www/issues) know. |
||||
|
|
||||
|
### Updating this Document |
||||
|
|
||||
|
If you think something should be added here, make a PR that includes the following: |
||||
|
|
||||
|
0. a summary |
||||
|
0. one or more example errors |
||||
|
0. steps to debug and fix |
||||
|
0. links to at least one related issue from the tracker |
||||
|
|
||||
|
For more details of the content and formatting of these entries, refer to examples below. |
||||
|
|
||||
|
## Table of Contents |
||||
|
|
||||
|
* [Upgrading npm](#upgrading-npm) |
||||
|
* [Proxies and Networking](#proxy-and-networking-issues) |
||||
|
* [Cannot find module](#cannot-find-module) |
||||
|
* [Shasum Check Fails](#shasum-check-fails) |
||||
|
* [No Git](#no-git) |
||||
|
|
||||
|
## Upgrading npm |
||||
|
|
||||
|
Whenever you get npm errors, it's a good idea to first check your npm version and upgrade to latest whenever possible. We still see people running npm@1 (!) and in those cases, installing the latest version of npm usually solves the problem. |
||||
|
|
||||
|
You can check your npm version by running `npm -v`. |
||||
|
|
||||
|
### Steps to Fix |
||||
|
* Upgrading on \*nix (OSX, Linux, etc.) |
||||
|
|
||||
|
(You may need to prefix these commands with sudo, especially on Linux, or OS X if you installed Node using its default installer.) |
||||
|
You can upgrade to the latest version of npm using: |
||||
|
`npm install -g npm@latest` |
||||
|
Or upgrade to the most recent LTS release: |
||||
|
`npm install -g npm@lts` |
||||
|
|
||||
|
* Upgrading on Windows |
||||
|
|
||||
|
We have a [detailed guide](https://github.com/npm/npm/wiki/Troubleshooting#upgrading-on-windows) for upgrading on windows on our wiki. |
||||
|
|
||||
|
## Proxy and Networking Issues |
||||
|
|
||||
|
npm might not be able to connect to the registry for various reasons. Perhaps your machine is behind a firewall that needs to be opened, or you require a corporate proxy to access the npm registry. This issue can manifest in a wide number of different ways. Usually, strange network errors are an instance of this specific problem. |
||||
|
|
||||
|
Sometimes, users may have install failures due to Git/Github access issues. Git/GitHub access is separate from npm registry access. For users in some locations (India in particular), problems installing packages may be due to connectivity problems reaching GitHub and not the npm registry. |
||||
|
|
||||
|
If you believe your network is configured and working correctly, and you're still having problems installing, please let the [registry team](https://github.com/npm/registry/issues) know you're having trouble. |
||||
|
|
||||
|
### Steps to Fix |
||||
|
|
||||
|
0. Make sure you have a working internet connection. Can you reach https://registry.npmjs.org? Can you reach other sites? If other sites are unreachable, this is not a problem with npm. |
||||
|
|
||||
|
0. Check http://status.npmjs.org/ for any potential current service outages. |
||||
|
|
||||
|
0. If your company has a process for domain whitelisting for developers, make sure https://registry.npmjs.org is a whitelisted domain. |
||||
|
|
||||
|
0. If you're in China, consider using https://npm.taobao.org/ as a registry, which sits behind the Firewall. |
||||
|
|
||||
|
0. On Windows, npm does not access proxies configured at the system level, so you need to configure them manually in order for npm to access them. Make sure [you have added the appropriate proxy configuration to `.npmrc`](https://docs.npmjs.com/misc/config#https-proxy). |
||||
|
|
||||
|
0. If you already have a proxy configured, it might be configured incorrectly or use the wrong credentials. Verify your credentials, test the specific credentials with a separate application. |
||||
|
|
||||
|
0. The proxy itself, on the server, might also have a configuration error. In this case, you'll need to work with your system administrator to verify that the proxy, and HTTPS, are configured correctly. You may test it by running regular HTTPS requests. |
||||
|
|
||||
|
### Example Errors |
||||
|
|
||||
|
This error can manifest in a wide range of different ways: |
||||
|
|
||||
|
``` |
||||
|
npm ERR! code UNABLE_TO_VERIFY_LEAF_SIGNATURE |
||||
|
npm ERR! unable to verify the first certificate |
||||
|
``` |
||||
|
``` |
||||
|
npm ERR! code UNABLE_TO_GET_ISSUER_CERT_LOCALLY |
||||
|
npm ERR! unable to get local issuer certificate |
||||
|
``` |
||||
|
``` |
||||
|
npm ERR! code DEPTH_ZERO_SELF_SIGNED_CERT |
||||
|
npm ERR! self signed certificate |
||||
|
``` |
||||
|
``` |
||||
|
124 error code ECONNREFUSED |
||||
|
125 error errno ECONNREFUSED |
||||
|
126 error syscall connect |
||||
|
``` |
||||
|
``` |
||||
|
136 error Unexpected token < |
||||
|
136 error <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
||||
|
136 error <HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
||||
|
136 error <TITLE>ERROR: Cache Access Denied</TITLE> |
||||
|
``` |
||||
|
``` |
||||
|
31 verbose stack Error: connect ETIMEDOUT 123.123.123.123:443 |
||||
|
``` |
||||
|
``` |
||||
|
108 error code EAI_AGAIN |
||||
|
109 error errno EAI_AGAIN |
||||
|
110 error syscall getaddrinfo |
||||
|
111 error getaddrinfo EAI_AGAIN proxy.yourcorp.com:811 |
||||
|
``` |
||||
|
``` |
||||
|
npm ERR! Error: getaddrinfo ESRCH |
||||
|
npm ERR! at errnoException (dns.js:37:11) |
||||
|
npm ERR! at Object.onanswer as oncomplete |
||||
|
``` |
||||
|
``` |
||||
|
35 error Unexpected token u |
||||
|
35 error function FindProxyForURL(url, host) { |
||||
|
``` |
||||
|
|
||||
|
### Related issues |
||||
|
* [#14318](https://github.com/npm/npm/issues/14318) |
||||
|
* [#15059](https://github.com/npm/npm/issues/15059) |
||||
|
* [#14336](https://github.com/npm/npm/issues/14336) |
||||
|
|
||||
|
## Cannot find module |
||||
|
|
||||
|
If *when running npm* (not your application), you get an error about a module not being found, this almost certainly means that there's something wrong with your npm installation. |
||||
|
|
||||
|
If this happens when trying to start your application, you might not have installed your package's dependencies yet. |
||||
|
|
||||
|
### Steps to Fix |
||||
|
|
||||
|
0. If this happens when you try to start your application, try running `npm install` to install the app's dependencies. Make sure all its actual dependencies are listed in `package.json` |
||||
|
|
||||
|
0. If this happens on any npm command, please reinstall. |
||||
|
|
||||
|
### Examples |
||||
|
|
||||
|
``` |
||||
|
module.js:338 |
||||
|
throw err; |
||||
|
^ |
||||
|
Error: Cannot find module |
||||
|
``` |
||||
|
### Related Issues |
||||
|
|
||||
|
* [#14699](https://github.com/npm/npm/issues/14699) |
||||
|
|
||||
|
## Shasum Check Fails |
||||
|
|
||||
|
This is a common issue which used to be caused by caching issues. Nowadays, the cache has been improved, so it's likely to be an install issue, which can be caused by network problems (sometimes even [proxy issues](#proxy-and-networking-issues)), a node bug, or possibly some sort of npm bug. |
||||
|
|
||||
|
### Steps to Fix |
||||
|
|
||||
|
0. Try running `npm install` again. It may have been a momentary hiccup or corruption during package download. |
||||
|
|
||||
|
0. Check http://status.npmjs.org/ for any potential current service outages. |
||||
|
|
||||
|
0. If the shasum error specifically has `Actual: da39a3ee5e6b4b0d3255bfef95601890afd80709`, with this exact shasum, it means the package download was empty, which is certainly a networking issue. |
||||
|
|
||||
|
0. Make sure your [network connection and proxy settings](#proxy-and-networking-issues) are ok. |
||||
|
|
||||
|
0. Update your node version to the latest stable version. |
||||
|
|
||||
|
### Examples |
||||
|
|
||||
|
``` |
||||
|
npm ERR! shasum check failed for C:\Users\some-user\AppData\Local\Temp\npm-9356-7 |
||||
|
d74e411\registry.npmjs.org\some-package\-\some-package-1.0.0.tgz |
||||
|
npm ERR! Expected: 652294c14651db29fa93bd2d5ff2983a4f08c636 |
||||
|
npm ERR! Actual: c45474b40e6a7474633ec6f2b0315feaf15c61f2 |
||||
|
npm ERR! From: https://registry.npmjs.org/some-package/-/some-package-1.0.0.tgz |
||||
|
``` |
||||
|
|
||||
|
### Related Issues |
||||
|
* [#14720](https://github.com/npm/npm/issues/14720) |
||||
|
* [#13405](https://github.com/npm/npm/issues/13405) |
||||
|
|
||||
|
## No Git |
||||
|
If your install fails and you see a message saying you don't have git installed, it should be resolved by installing git. |
||||
|
|
||||
|
### Steps to Fix |
||||
|
|
||||
|
0. [Install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) following the instructions for your machine. |
||||
|
|
||||
|
### Examples |
||||
|
|
||||
|
npm ERR! not found: git |
||||
|
ENOGIT |
||||
|
|
||||
|
### Related Issues |
||||
|
|
||||
|
* [#11095](https://github.com/npm/npm/issues/11095) |
@ -0,0 +1,142 @@ |
|||||
|
var log = require('npmlog') |
||||
|
var npm = require('../npm.js') |
||||
|
var read = require('read') |
||||
|
var userValidate = require('npm-user-validate') |
||||
|
var output = require('../utils/output') |
||||
|
var chain = require('slide').chain |
||||
|
|
||||
|
module.exports.login = function login (creds, registry, scope, cb) { |
||||
|
var c = { |
||||
|
u: creds.username || '', |
||||
|
p: creds.password || '', |
||||
|
e: creds.email || '' |
||||
|
} |
||||
|
var u = {} |
||||
|
|
||||
|
chain([ |
||||
|
[readUsername, c, u], |
||||
|
[readPassword, c, u], |
||||
|
[readEmail, c, u], |
||||
|
[save, c, u, registry, scope] |
||||
|
], function (err, res) { |
||||
|
cb(err, res && res[res.length - 1]) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function readUsername (c, u, cb) { |
||||
|
var v = userValidate.username |
||||
|
read({prompt: 'Username: ', default: c.u || ''}, function (er, un) { |
||||
|
if (er) { |
||||
|
return cb(er.message === 'cancelled' ? er.message : er) |
||||
|
} |
||||
|
|
||||
|
// make sure it's valid. we have to do this here, because
|
||||
|
// couchdb will only ever say "bad password" with a 401 when
|
||||
|
// you try to PUT a _users record that the validate_doc_update
|
||||
|
// rejects for *any* reason.
|
||||
|
|
||||
|
if (!un) { |
||||
|
return readUsername(c, u, cb) |
||||
|
} |
||||
|
|
||||
|
var error = v(un) |
||||
|
if (error) { |
||||
|
log.warn(error.message) |
||||
|
return readUsername(c, u, cb) |
||||
|
} |
||||
|
|
||||
|
c.changed = c.u !== un |
||||
|
u.u = un |
||||
|
cb(er) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function readPassword (c, u, cb) { |
||||
|
var v = userValidate.pw |
||||
|
|
||||
|
var prompt |
||||
|
if (c.p && !c.changed) { |
||||
|
prompt = 'Password: (or leave unchanged) ' |
||||
|
} else { |
||||
|
prompt = 'Password: ' |
||||
|
} |
||||
|
|
||||
|
read({prompt: prompt, silent: true}, function (er, pw) { |
||||
|
if (er) { |
||||
|
return cb(er.message === 'cancelled' ? er.message : er) |
||||
|
} |
||||
|
|
||||
|
if (!c.changed && pw === '') { |
||||
|
// when the username was not changed,
|
||||
|
// empty response means "use the old value"
|
||||
|
pw = c.p |
||||
|
} |
||||
|
|
||||
|
if (!pw) { |
||||
|
return readPassword(c, u, cb) |
||||
|
} |
||||
|
|
||||
|
var error = v(pw) |
||||
|
if (error) { |
||||
|
log.warn(error.message) |
||||
|
return readPassword(c, u, cb) |
||||
|
} |
||||
|
|
||||
|
c.changed = c.changed || c.p !== pw |
||||
|
u.p = pw |
||||
|
cb(er) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function readEmail (c, u, cb) { |
||||
|
var v = userValidate.email |
||||
|
var r = { prompt: 'Email: (this IS public) ', default: c.e || '' } |
||||
|
read(r, function (er, em) { |
||||
|
if (er) { |
||||
|
return cb(er.message === 'cancelled' ? er.message : er) |
||||
|
} |
||||
|
|
||||
|
if (!em) { |
||||
|
return readEmail(c, u, cb) |
||||
|
} |
||||
|
|
||||
|
var error = v(em) |
||||
|
if (error) { |
||||
|
log.warn(error.message) |
||||
|
return readEmail(c, u, cb) |
||||
|
} |
||||
|
|
||||
|
u.e = em |
||||
|
cb(er) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function save (c, u, registry, scope, cb) { |
||||
|
var params = { |
||||
|
auth: { |
||||
|
username: u.u, |
||||
|
password: u.p, |
||||
|
email: u.e |
||||
|
} |
||||
|
} |
||||
|
npm.registry.adduser(registry, params, function (er, doc) { |
||||
|
if (er) return cb(er) |
||||
|
|
||||
|
var newCreds = (doc && doc.token) |
||||
|
? { |
||||
|
token: doc.token |
||||
|
} |
||||
|
: { |
||||
|
username: u.u, |
||||
|
password: u.p, |
||||
|
email: u.e, |
||||
|
alwaysAuth: npm.config.get('always-auth') |
||||
|
} |
||||
|
|
||||
|
log.info('adduser', 'Authorized user %s', u.u) |
||||
|
var scopeMessage = scope ? ' to scope ' + scope : '' |
||||
|
output('Logged in as %s%s on %s.', u.u, scopeMessage, registry) |
||||
|
|
||||
|
cb(null, newCreds) |
||||
|
}) |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
var ssoAuth = require('./sso') |
||||
|
var npm = require('../npm') |
||||
|
|
||||
|
module.exports.login = function login () { |
||||
|
npm.config.set('sso-type', 'oauth') |
||||
|
ssoAuth.login.apply(this, arguments) |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
var ssoAuth = require('./sso') |
||||
|
var npm = require('../npm') |
||||
|
|
||||
|
module.exports.login = function login () { |
||||
|
npm.config.set('sso-type', 'saml') |
||||
|
ssoAuth.login.apply(this, arguments) |
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
var log = require('npmlog') |
||||
|
var npm = require('../npm.js') |
||||
|
var output = require('../utils/output') |
||||
|
var opener = require('opener') |
||||
|
|
||||
|
module.exports.login = function login (creds, registry, scope, cb) { |
||||
|
var ssoType = npm.config.get('sso-type') |
||||
|
if (!ssoType) { return cb(new Error('Missing option: sso-type')) } |
||||
|
|
||||
|
var params = { |
||||
|
// We're reusing the legacy login endpoint, so we need some dummy
|
||||
|
// stuff here to pass validation. They're never used.
|
||||
|
auth: { |
||||
|
username: 'npm_' + ssoType + '_auth_dummy_user', |
||||
|
password: 'placeholder', |
||||
|
email: 'support@npmjs.com', |
||||
|
authType: ssoType |
||||
|
} |
||||
|
} |
||||
|
npm.registry.adduser(registry, params, function (er, doc) { |
||||
|
if (er) return cb(er) |
||||
|
if (!doc || !doc.token) return cb(new Error('no SSO token returned')) |
||||
|
if (!doc.sso) return cb(new Error('no SSO URL returned by services')) |
||||
|
|
||||
|
output('If your browser doesn\'t open, visit ' + |
||||
|
doc.sso + |
||||
|
' to complete authentication') |
||||
|
opener(doc.sso, { command: npm.config.get('browser') }, function () { |
||||
|
pollForSession(registry, doc.token, function (err, username) { |
||||
|
if (err) return cb(err) |
||||
|
|
||||
|
log.info('adduser', 'Authorized user %s', username) |
||||
|
var scopeMessage = scope ? ' to scope ' + scope : '' |
||||
|
output('Logged in as %s%s on %s.', username, scopeMessage, registry) |
||||
|
|
||||
|
cb(null, { token: doc.token }) |
||||
|
}) |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function pollForSession (registry, token, cb) { |
||||
|
log.info('adduser', 'Polling for validated SSO session') |
||||
|
npm.registry.whoami(registry, { |
||||
|
auth: { |
||||
|
token: token |
||||
|
} |
||||
|
}, function (er, username) { |
||||
|
if (er && er.statusCode !== 401) { |
||||
|
cb(er) |
||||
|
} else if (!username) { |
||||
|
setTimeout(function () { |
||||
|
pollForSession(registry, token, cb) |
||||
|
}, npm.config.get('sso-poll-frequency')) |
||||
|
} else { |
||||
|
cb(null, username) |
||||
|
} |
||||
|
}) |
||||
|
} |
@ -1,8 +0,0 @@ |
|||||
'use strict' |
|
||||
var lifecycle = require('../../utils/lifecycle.js') |
|
||||
var packageId = require('../../utils/package-id.js') |
|
||||
|
|
||||
module.exports = function (staging, pkg, log, next) { |
|
||||
log.silly('test', packageId(pkg)) |
|
||||
lifecycle(pkg.package, 'test', pkg.path, false, false, next) |
|
||||
} |
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue