Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot link to binary #25284

Closed
johnramsden opened this issue Apr 28, 2017 · 11 comments
Closed

Cannot link to binary #25284

johnramsden opened this issue Apr 28, 2017 · 11 comments

Comments

@johnramsden
Copy link
Member

johnramsden commented Apr 28, 2017

Issue description

I've been trying for days to figure this out and I figured if I asked here someone might be able to point out what is going wrong.


So my original problem below with libxkb has been solved thanks to @pbogdan, and now I'm having problems with the keyring.

I went into detail below but basically I'm unable to figure out how to register this application with the gnome keyring. Preferably I would register it with my kde kwallet, but I think it will only work with a gnome keyring. Maybe someone could correct me if this is wrong.


I've patched a package with patchelf, nylas-mail and all of the libraries have been linked normally except for one, libxkbfile. When I run ldd it's missing, I even tried adding it explicitly with: patchelf --set-rpath $ffrp:$out/lib:${stdenv.cc.cc.lib}/lib:${xorg.libxkbfile.out}/lib:${lib.makeLibraryPath propagatedBuildInputs } and it won't add it.

Here's the full config.

Steps to reproduce

Patch a binary using patchelf, when attempting to run I end up with.

Error: libxkbfile.so.1: cannot open shared object file: No such file or directory

The full error can be seen here.

Running ldd on the binary you can see it is clearly not linking to it properly.

ldd /nix/store/nxr2gh88biadc7p5qsz43dx8j6yjfanp-packaged-nylas-mail-2.0.16/usr/bin/nylas-mail | grep libxkbfile

It brings up nothing.

Technical details

  • System: (NixOS: 17.03.928.69d9061908 (Gorilla))
  • Nix version: (nix-env (Nix) 1.11.8)
  • Nixpkgs version: ("17.03.928.69d9061908")
@pbogdan
Copy link
Member

pbogdan commented Apr 29, 2017

Someone will hopefully correct me if I'm wrong but I believe the issue here is that some of the libraries are being loaded dynamically at runtime via dlopen() which doesn't search through RUNPATH. One solution is to wrap the original binary while setting $LD_LIBRARY_PATH as needed:

--- default.orig.nix    2017-04-29 15:09:38.386806062 +0100
+++ default.nix 2017-04-29 16:38:36.801235529 +0100
@@ -27,6 +27,7 @@
 , udev
 , libxkbcommon
 , xorg
+, makeWrapper
 }:

 stdenv.mkDerivation rec {
@@ -79,6 +80,8 @@
      xorg.libxkbfile
    ];

+   buildInputs = [ makeWrapper ];
+
    phases = [ "unpackPhase" ];

    unpackPhase = ''
@@ -100,6 +103,8 @@
      patchelf --interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
          --set-rpath $binrp:$out/lib:${stdenv.cc.cc.lib}/lib:${lib.makeLibraryPath propagatedBuildInputs } \
          $out/usr/share/nylas-mail/nylas
+     wrapProgram $out/usr/share/nylas-mail/nylas \
+      --set LD_LIBRARY_PATH "${xorg.libxkbfile}/lib:${libgnome_keyring}/lib";
    '';

    meta = {

When invoked via wrapper the application starts without on issues for me but I haven't tested any of the functionality. HTH.

@johnramsden
Copy link
Member Author

Thanks @pbogdan! It works!

@johnramsden
Copy link
Member Author

@pbogdan Do you happen to know how I would use kwallet as a keyring, instead, or in addition to gnome keyring? I couldn't find much information on it.

@johnramsden johnramsden reopened this Apr 29, 2017
@johnramsden
Copy link
Member Author

So, Now Nylas-Mail does start running but unfortunately because I'm using KDE, and I don't have gnome-keyring setup, the application complains that it can't store my password securely. I tried enabling gnome keyring and starting it in pam with:

gnome3.gnome-keyring.enable = true;
pam.services = [
      { name = "gnome_keyring";
        text = ''
          auth     optional    ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so
          session  optional    ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start

          password	optional	${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so
        '';
      }
    ];

Unfortunately this didn't seem to make a difference.

Here's the error that gets spit out when it tells me I can't store my passwords securely.

** Message: secret service operation failed: Type of message, '(a{sv})', does not match expected type '(a{sv}s)'
{ Error: Password Management Error: We couldn't store your password securely! For more information, visit https://support.nylas.com/hc/en-us/articles/223790028
    at KeyManager._try (/src/key-manager.es6:70:30)
    at KeyManager.deletePassword (/src/key-manager.es6:36:10)
    at /src/flux/stores/identity-store.es6:92:18
    at next (<anonymous>)
    at step (/src/flux/stores/identity-store.es6:11:1)
    at Promise._execute (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/debuggability.js:300:9)
    at Promise._resolveFromExecutor (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:481:18)
    at new Promise (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:77:14)
    at /src/flux/stores/identity-store.es6:11:1
    at IdentityStore.<anonymous> (/src/flux/stores/identity-store.es6:124:16)
    at next (<anonymous>)
    at step (/src/flux/stores/identity-store.es6:11:1)
    at Promise._execute (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/debuggability.js:300:9)
    at Promise._resolveFromExecutor (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:481:18)
    at new Promise (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:77:14)
    at IdentityStore._onLogoutNylasIdentity (/src/flux/stores/identity-store.es6:11:1)
    at EventEmitter.eventHandler (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/reflux/src/PublisherMethods.js:36:22)
    at EventEmitter.emit (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/eventemitter3/index.js:72:35)
    at Function.trigger (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/reflux/src/PublisherMethods.js:52:26)
    at Function.functor [as logoutNylasIdentity] (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/reflux/src/createAction.js:32:56)
    at NylasAPIRequest._defaultAuth (/src/flux/nylas-api-request.es6:154:19)
    at /src/flux/nylas-api-request.es6:35:53
    at next (<anonymous>)
    at step (/src/flux/nylas-api-request.es6:7:1)
    at Promise._execute (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/debuggability.js:300:9)
    at Promise._resolveFromExecutor (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:481:18)
    at new Promise (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:77:14)
    at /src/flux/nylas-api-request.es6:7:1
    at ContactRankingsCache.fetchData.callback [as fetchData] (/internal_packages/contact-rankings/lib/contact-rankings-cache.es6:47:13)
    at ContactRankingsCache.RefreshingJSONCache.refresh (/internal_packages/contact-rankings/lib/refreshing-json-cache.coffee:43:6)
    at /internal_packages/contact-rankings/lib/refreshing-json-cache.coffee:1:1
  message: 'Password Management Error: We couldn\'t store your password securely! For more information, visit https://support.nylas.com/hc/en-us/articles/223790028' } {}
{ Error
    at new APIError (/src/flux/errors.es6:57:19)
    at NylasAPIRequest._defaultAuth (/src/flux/nylas-api-request.es6:170:13)
    at /src/flux/nylas-api-request.es6:35:53
    at next (<anonymous>)
    at step (/src/flux/nylas-api-request.es6:7:1)
    at Promise._execute (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/debuggability.js:300:9)
    at Promise._resolveFromExecutor (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:481:18)
    at new Promise (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:77:14)
    at /src/flux/nylas-api-request.es6:7:1
    at ContactRankingsCache.fetchData.callback [as fetchData] (/internal_packages/contact-rankings/lib/contact-rankings-cache.es6:47:13)
    at ContactRankingsCache.RefreshingJSONCache.refresh (/internal_packages/contact-rankings/lib/refreshing-json-cache.coffee:43:6)
    at /internal_packages/contact-rankings/lib/refreshing-json-cache.coffee:1:1
  name: 'APIError',
  error: 
   { stack: 'Error: No Identity\n    at NylasAPIRequest._defaultAuth (/src/flux/nylas-api-request.es6:156:15)\n    at /src/flux/nylas-api-request.es6:35:53\n    at next (<anonymous>)\n    at step (/src/flux/nylas-api-request.es6:7:1)\n    at Promise._execute (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/debuggability.js:300:9)\n    at Promise._resolveFromExecutor (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:481:18)\n    at new Promise (/nix/store/q23wkh2cg9489a70127xg05510awcr3z-packaged-nylas-mail-2.0.16/share/nylas-mail/resources/app.asar/node_modules/bluebird/js/release/promise.js:77:14)\n    at /src/flux/nylas-api-request.es6:7:1\n    at ContactRankingsCache.fetchData.callback [as fetchData] (/internal_packages/contact-rankings/lib/contact-rankings-cache.es6:47:13)\n    at ContactRankingsCache.RefreshingJSONCache.refresh (/internal_packages/contact-rankings/lib/refreshing-json-cache.coffee:43:6)\n    at /internal_packages/contact-rankings/lib/refreshing-json-cache.coffee:1:1',
     message: 'No Identity' },
  requestOptions: null,
  statusCode: 400,
  message: 'No Identity',
  errorType: null } {}

@johnramsden johnramsden changed the title Cannot link patched package to libxkbfile Cannot use keyring with custom package Apr 30, 2017
@pbogdan
Copy link
Member

pbogdan commented Apr 30, 2017

Sorry, by looking at the inputs I assumed it was supposed to be using gnome2's libgnome-keyring and I'm guessing that's not compatible with gnome3 keyring daemon and its interface. Try changing:

     wrapProgram $out/usr/share/nylas-mail/nylas \
      --set LD_LIBRARY_PATH "${xorg.libxkbfile}/lib:${libgnome_keyring}/lib";

to:

     wrapProgram $out/usr/share/nylas-mail/nylas \
      --set LD_LIBRARY_PATH "${xorg.libxkbfile}/lib:${gnome3.libgnome_keyring}/lib";

With that change I get a prompt about creating a new keyring and seems to save the credentials successfully.

@johnramsden
Copy link
Member Author

@pbogdan Nice, that worked.

Do you know it would be possible to do the same thing with Kwallet? I use KDE and unless it's absolutely necessary I'd rather not be running two keyrings. Or is this kind of thing usually keyring specific?

@johnramsden
Copy link
Member Author

Hmm, I'm also having a problem with the plugins not showing up that I think might be NixOS related. When I enable debugging you can see it's searching for something in the Nix store and being unable to find it. Maybe it's something related to how Nix cleans up the packages?

Here's the error I get logged to the console:

"Error: Fetching local packages failed.
    at createProcessError (/src/apm-wrapper.coffee:276:15)
    at /src/apm-wrapper.coffee:284:14
    at Function.module.exports.Emitter.simpleDispatch (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/event-kit/lib/emitter.js:25:14)
    at Emitter.module.exports.Emitter.emit (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/event-kit/lib/emitter.js:125:28)
    at BufferedProcess.module.exports.BufferedProcess.handleError (/src/buffered-process.coffee:238:14)
    at ChildProcess.<anonymous> (/src/buffered-process.coffee:231:38)
    at emitOne (events.js:96:13)
    at ChildProcess.emit (events.js:188:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:213:12)
    at onErrorNT (internal/child_process.js:359:16)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickDomainCallback (internal/process/next_tick.js:122:9)
From previous event:
    at APMWrapper.module.exports.APMWrapper.getInstalled (/src/apm-wrapper.coffee:90:5)
    at Store._onPackagesChanged (/internal_packages/plugins/lib/packages-store.jsx:189:15)
    at Store._refreshInstalled (/internal_packages/plugins/lib/packages-store.jsx:165:10)
    at EventEmitter.eventHandler (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/reflux/src/PublisherMethods.js:36:22)
    at EventEmitter.emit (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/eventemitter3/index.js:72:35)
    at Function.trigger (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/reflux/src/PublisherMethods.js:52:26)
    at Object.functor [as refreshInstalledPackages] (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/reflux/src/createAction.js:32:56)
    at TabInstalled.componentDidMount (/internal_packages/plugins/lib/tab-installed.jsx:23:20)
    at measureLifeCyclePerf (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12)
    at /nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/ReactCompositeComponent.js:264:11
    at CallbackQueue.notifyAll (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/CallbackQueue.js:76:22)
    at ReactReconcileTransaction.close (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/ReactReconcileTransaction.js:80:26)
    at ReactReconcileTransaction.closeAll (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/Transaction.js:206:25)
    at ReactReconcileTransaction.perform (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/Transaction.js:153:16)
    at ReactUpdatesFlushTransaction.perform (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/Transaction.js:140:20)
    at Object.flushBatchedUpdates (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/ReactUpdates.js:172:19)
    at ReactDefaultBatchingStrategyTransaction.closeAll (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/Transaction.js:206:25)
    at ReactDefaultBatchingStrategyTransaction.perform (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/Transaction.js:153:16)
    at dispatchEvent (/nix/store/xvsmh0ph14zk1jdl422c6bfdrdskqfsr-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/app.asar/node_modules/react-dom/lib/ReactEventListener.js:147:20)"

@pbogdan
Copy link
Member

pbogdan commented May 1, 2017

Ugh, this is ugly but give this a try:

--- default.orig.nix    2017-04-29 15:09:38.386806062 +0100
+++ default.nix 2017-05-01 11:55:30.565250705 +0100
@@ -5,6 +5,7 @@
 , dpkg
 , lib
 , gnome2
+, gnome3
 , libgnome_keyring
 , desktop_file_utils
 , python2
@@ -27,6 +28,9 @@
 , udev
 , libxkbcommon
 , xorg
+, makeWrapper
+, gcc-unwrapped
+, coreutils
 }:

 stdenv.mkDerivation rec {
@@ -43,7 +47,7 @@
    propagatedBuildInputs = [
      gnome2.gtk
      gnome2.GConf
-     gnome2.gnome_keyring
+     gnome3.gnome_keyring
      libgnome_keyring
      desktop_file_utils
      python2
@@ -79,6 +83,8 @@
      xorg.libxkbfile
    ];

+   buildInputs = [ makeWrapper ];
+
    phases = [ "unpackPhase" ];

    unpackPhase = ''
@@ -100,6 +106,16 @@
      patchelf --interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
          --set-rpath $binrp:$out/lib:${stdenv.cc.cc.lib}/lib:${lib.makeLibraryPath propagatedBuildInputs } \
          $out/usr/share/nylas-mail/nylas
+     wrapProgram $out/usr/share/nylas-mail/nylas \
+         --set LD_LIBRARY_PATH "${xorg.libxkbfile}/lib:${gnome3.libgnome_keyring}/lib";
+
+      sed -i 's|/bin/bash|${stdenv.shell}|' $out/usr/share/nylas-mail/resources/apm/bin/apm
+      wrapProgram $out/usr/share/nylas-mail/resources/apm/bin/apm \
+          --set PATH "${coreutils}/bin"
+
+      patchelf --interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+          --set-rpath ${gcc-unwrapped.lib}/lib \
+          $out/usr/share/nylas-mail/resources/apm/bin/node
    '';

    meta = {

Far as I can tell the issue is that plugin management requires launching $out/usr/share/nylas-mail/resources/apm/bin/apm script which has its interpreter set to /bin/bash. Secondly for reasons unknown the script gets launched without inheriting any of the env variables such as $PATH so it can't find dirname and friends hence the need for a wrapper to provide coreutils on the path. And finally the script launches bundled nodejs executable which needs to be patched..
Mind you this is very much brute force approach so there may well be a cleaner / more idiomatic solution but seems to work for me in terms of listing / installing plugins.
And sorry - not sure about keyrings but my guess would be that they can't be easily swapped.

@johnramsden
Copy link
Member Author

johnramsden commented May 4, 2017

Hmm, that diddn't work for me with the changes applied.

I'm getting this logged:

nylas-mail %U                                                                                john@atom
Streaming log data to /tmp/Nylas-Mail-3911.log
App load time: 275ms
{ Error: Fetching local packages failed.
    at /src/apm-wrapper.coffee:44:21
    at exit (/src/apm-wrapper.coffee:20:7)
    at triggerExitCallback (/src/buffered-process.coffee:210:9)
    at /src/buffered-process.coffee:216:9
    at Socket.<anonymous> (/src/buffered-process.coffee:123:7)
    at emitOne (events.js:101:20)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:493:12)
  name: 'Error',
  message: 'Fetching local packages failed.',
  cause: 
   { stack: 'Error: Fetching local packages failed.\n    at /src/apm-wrapper.coffee:44:21\n    at exit (/src/apm-wrapper.coffee:20:7)\n    at triggerExitCallback (/src/buffered-process.coffee:210:9)\n    at /src/buffered-process.coffee:216:9\n    at Socket.<anonymous> (/src/buffered-process.coffee:123:7)\n    at emitOne (events.js:101:20)\n    at Socket.emit (events.js:188:7)\n    at Pipe._handle.close [as _onclose] (net.js:493:12)',
     message: 'Fetching local packages failed.',
     stdout: '',
     stderr: '/nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/apm: /nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/.apm-wrapped: /bin/bash: bad interpreter: No such file or directory\n/nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/apm: line 3: /nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/.apm-wrapped: Success\n' },
  isOperational: true,
  stdout: '',
  stderr: '/nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/apm: /nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/.apm-wrapped: /bin/bash: bad interpreter: No such file or directory\n/nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/apm: line 3: /nix/store/yc79q6bwscnnjp0zrlal4rawz7wxipp0-packaged-nylas-mail-2.0.31/share/nylas-mail/resources/apm/bin/.apm-wrapped: Success\n' } { pluginIds: [] }
Creation of this event was denied due to rate limiting
429
IncomingMessage {
  _readableState: 
   ReadableState {
     objectMode: false,
     highWaterMark: 16384,
     buffer: BufferList { head: null, tail: null, length: 0 },
     length: 0,
     pipes: null,
     pipesCount: 0,
     flowing: null,
     ended: false,
     endEmitted: false,
     reading: false,
     sync: true,
     needReadable: false,
     emittedReadable: false,
     readableListening: false,
     resumeScheduled: false,
     defaultEncoding: 'utf8',
     ranOut: false,
     awaitDrain: 0,
     readingMore: true,
     decoder: 
      StringDecoder {
        encoding: 'utf8',
        fillLast: [Function: utf8FillLast],
        lastNeed: 0,
        lastTotal: 0,
        lastChar: <Buffer 00 00 00 00> },
     encoding: 'utf8' },
  readable: true,
  domain: null,
  _events: { end: [Function: responseOnEnd] },
  _eventsCount: 1,
  _maxListeners: undefined,
  socket: 
   TLSSocket {
     _tlsOptions: 
      { pipe: null,
        secureContext: [Object],
        isServer: false,
        requestCert: true,
        rejectUnauthorized: true,
        session: undefined,
        NPNProtocols: undefined,
        ALPNProtocols: undefined,
        requestOCSP: undefined },
     _secureEstablished: true,
     _securePending: false,
     _newSessionPending: false,
     _controlReleased: true,
     _SNICallback: null,
     servername: null,
     npnProtocol: false,
     alpnProtocol: false,
     authorized: true,
     authorizationError: null,
     encrypted: true,
     _events: 
      { close: [Object],
        end: [Object],
        finish: [Function: onSocketFinish],
        _socketEnd: [Function: onSocketEnd],
        secure: [Function],
        free: [Function: onFree],
        agentRemove: [Function: onRemove],
        drain: [Function: ondrain],
        error: [Function: socketErrorListener],
        data: [Function: socketOnData] },
     _eventsCount: 10,
     connecting: false,
     _hadError: false,
     _handle: 
      TLSWrap {
        bytesRead: 700,
        _externalStream: {},
        fd: 73,
        _parent: [Object],
        _parentWrap: undefined,
        _secureContext: [Object],
        reading: true,
        owner: [Circular],
        onread: [Function: onread],
        writeQueueSize: 1,
        onhandshakestart: [Function],
        onhandshakedone: [Function],
        onocspresponse: [Function],
        onerror: [Function] },
     _parent: null,
     _host: 'sentry.io',
     _readableState: 
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: [Object],
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: false,
        sync: false,
        needReadable: true,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        defaultEncoding: 'utf8',
        ranOut: false,
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: true,
     domain: null,
     _maxListeners: undefined,
     _writableState: 
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 0,
        prefinished: false,
        errorEmitted: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: false,
     destroyed: false,
     _bytesDispatched: 2563,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: undefined,
     _server: null,
     ssl: 
      TLSWrap {
        bytesRead: 700,
        _externalStream: {},
        fd: 73,
        _parent: [Object],
        _parentWrap: undefined,
        _secureContext: [Object],
        reading: true,
        owner: [Circular],
        onread: [Function: onread],
        writeQueueSize: 1,
        onhandshakestart: [Function],
        onhandshakedone: [Function],
        onocspresponse: [Function],
        onerror: [Function] },
     _requestCert: true,
     _rejectUnauthorized: true,
     parser: 
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': null,
        _headers: [],
        _url: '',
        _consumed: false,
        socket: [Circular],
        incoming: [Circular],
        outgoing: [Object],
        maxHeaderPairs: 2000,
        onIncoming: [Function: parserOnIncomingClient] },
     _httpMessage: 
      ClientRequest {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedHeader: [Object],
        _contentLength: 2232,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Circular],
        connection: [Circular],
        _header: 'POST /api/144447/store/ HTTP/1.1\r\nX-Sentry-Auth: Sentry sentry_version=5, sentry_timestamp=1493865130216, sentry_client=raven-node/1.1.4, sentry_key=a556c0165bc74435952c95dccc5938ec, sentry_secret=484978beb99f40208cb86610e66bead6\r\nContent-Type: application/octet-stream\r\nContent-Length: 2232\r\nHost: sentry.io\r\nConnection: close\r\n\r\n',
        _headers: [Object],
        _headerNames: [Object],
        _onPendingData: null,
        agent: [Object],
        socketPath: undefined,
        method: 'POST',
        path: '/api/144447/store/',
        _ended: false,
        parser: [Object],
        res: [Circular] },
     read: [Function],
     _consuming: true },
  connection: 
   TLSSocket {
     _tlsOptions: 
      { pipe: null,
        secureContext: [Object],
        isServer: false,
        requestCert: true,
        rejectUnauthorized: true,
        session: undefined,
        NPNProtocols: undefined,
        ALPNProtocols: undefined,
        requestOCSP: undefined },
     _secureEstablished: true,
     _securePending: false,
     _newSessionPending: false,
     _controlReleased: true,
     _SNICallback: null,
     servername: null,
     npnProtocol: false,
     alpnProtocol: false,
     authorized: true,
     authorizationError: null,
     encrypted: true,
     _events: 
      { close: [Object],
        end: [Object],
        finish: [Function: onSocketFinish],
        _socketEnd: [Function: onSocketEnd],
        secure: [Function],
        free: [Function: onFree],
        agentRemove: [Function: onRemove],
        drain: [Function: ondrain],
        error: [Function: socketErrorListener],
        data: [Function: socketOnData] },
     _eventsCount: 10,
     connecting: false,
     _hadError: false,
     _handle: 
      TLSWrap {
        bytesRead: 700,
        _externalStream: {},
        fd: 73,
        _parent: [Object],
        _parentWrap: undefined,
        _secureContext: [Object],
        reading: true,
        owner: [Circular],
        onread: [Function: onread],
        writeQueueSize: 1,
        onhandshakestart: [Function],
        onhandshakedone: [Function],
        onocspresponse: [Function],
        onerror: [Function] },
     _parent: null,
     _host: 'sentry.io',
     _readableState: 
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: [Object],
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: false,
        sync: false,
        needReadable: true,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        defaultEncoding: 'utf8',
        ranOut: false,
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: true,
     domain: null,
     _maxListeners: undefined,
     _writableState: 
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 0,
        prefinished: false,
        errorEmitted: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: false,
     destroyed: false,
     _bytesDispatched: 2563,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: undefined,
     _server: null,
     ssl: 
      TLSWrap {
        bytesRead: 700,
        _externalStream: {},
        fd: 73,
        _parent: [Object],
        _parentWrap: undefined,
        _secureContext: [Object],
        reading: true,
        owner: [Circular],
        onread: [Function: onread],
        writeQueueSize: 1,
        onhandshakestart: [Function],
        onhandshakedone: [Function],
        onocspresponse: [Function],
        onerror: [Function] },
     _requestCert: true,
     _rejectUnauthorized: true,
     parser: 
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': null,
        _headers: [],
        _url: '',
        _consumed: false,
        socket: [Circular],
        incoming: [Circular],
        outgoing: [Object],
        maxHeaderPairs: 2000,
        onIncoming: [Function: parserOnIncomingClient] },
     _httpMessage: 
      ClientRequest {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedHeader: [Object],
        _contentLength: 2232,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Circular],
        connection: [Circular],
        _header: 'POST /api/144447/store/ HTTP/1.1\r\nX-Sentry-Auth: Sentry sentry_version=5, sentry_timestamp=1493865130216, sentry_client=raven-node/1.1.4, sentry_key=a556c0165bc74435952c95dccc5938ec, sentry_secret=484978beb99f40208cb86610e66bead6\r\nContent-Type: application/octet-stream\r\nContent-Length: 2232\r\nHost: sentry.io\r\nConnection: close\r\n\r\n',
        _headers: [Object],
        _headerNames: [Object],
        _onPendingData: null,
        agent: [Object],
        socketPath: undefined,
        method: 'POST',
        path: '/api/144447/store/',
        _ended: false,
        parser: [Object],
        res: [Circular] },
     read: [Function],
     _consuming: true },
  httpVersionMajor: 1,
  httpVersionMinor: 1,
  httpVersion: '1.1',
  complete: false,
  headers: 
   { server: 'nginx',
     date: 'Thu, 04 May 2017 02:32:10 GMT',
     'content-type': 'application/json',
     'content-length': '92',
     connection: 'close',
     expires: 'Thu, 04 May 2017 02:32:10 GMT',
     'x-content-type-options': 'nosniff',
     'content-language': 'en',
     'x-sentry-error': 'Creation of this event was denied due to rate limiting',
     vary: 'Accept-Language, Cookie',
     'retry-after': '49.314729929',
     'last-modified': 'Thu, 04 May 2017 02:32:10 GMT',
     'x-xss-protection': '1; mode=block',
     'cache-control': 'max-age=0',
     'x-frame-options': 'deny',
     'x-served-by': 'app-ad953e',
     'strict-transport-security': 'max-age=31536000; includeSubDomains; preload' },
  rawHeaders: 
   [ 'Server',
     'nginx',
     'Date',
     'Thu, 04 May 2017 02:32:10 GMT',
     'Content-Type',
     'application/json',
     'Content-Length',
     '92',
     'Connection',
     'close',
     'Expires',
     'Thu, 04 May 2017 02:32:10 GMT',
     'X-Content-Type-Options',
     'nosniff',
     'Content-Language',
     'en',
     'X-Sentry-Error',
     'Creation of this event was denied due to rate limiting',
     'Vary',
     'Accept-Language, Cookie',
     'Retry-After',
     '49.314729929',
     'Last-Modified',
     'Thu, 04 May 2017 02:32:10 GMT',
     'X-XSS-Protection',
     '1; mode=block',
     'Cache-Control',
     'max-age=0',
     'X-Frame-Options',
     'deny',
     'X-Served-By',
     'app-ad953e',
     'Strict-Transport-Security',
     'max-age=31536000; includeSubDomains; preload' ],
  trailers: {},
  rawTrailers: [],
  upgrade: false,
  url: '',
  method: null,
  statusCode: 429,
  statusMessage: 'TOO MANY REQUESTS',
  client: 
   TLSSocket {
     _tlsOptions: 
      { pipe: null,
        secureContext: [Object],
        isServer: false,
        requestCert: true,
        rejectUnauthorized: true,
        session: undefined,
        NPNProtocols: undefined,
        ALPNProtocols: undefined,
        requestOCSP: undefined },
     _secureEstablished: true,
     _securePending: false,
     _newSessionPending: false,
     _controlReleased: true,
     _SNICallback: null,
     servername: null,
     npnProtocol: false,
     alpnProtocol: false,
     authorized: true,
     authorizationError: null,
     encrypted: true,
     _events: 
      { close: [Object],
        end: [Object],
        finish: [Function: onSocketFinish],
        _socketEnd: [Function: onSocketEnd],
        secure: [Function],
        free: [Function: onFree],
        agentRemove: [Function: onRemove],
        drain: [Function: ondrain],
        error: [Function: socketErrorListener],
        data: [Function: socketOnData] },
     _eventsCount: 10,
     connecting: false,
     _hadError: false,
     _handle: 
      TLSWrap {
        bytesRead: 700,
        _externalStream: {},
        fd: 73,
        _parent: [Object],
        _parentWrap: undefined,
        _secureContext: [Object],
        reading: true,
        owner: [Circular],
        onread: [Function: onread],
        writeQueueSize: 1,
        onhandshakestart: [Function],
        onhandshakedone: [Function],
        onocspresponse: [Function],
        onerror: [Function] },
     _parent: null,
     _host: 'sentry.io',
     _readableState: 
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: [Object],
        length: 0,
        pipes: null,
        pipesCount: 0,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: false,
        sync: false,
        needReadable: true,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        defaultEncoding: 'utf8',
        ranOut: false,
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: true,
     domain: null,
     _maxListeners: undefined,
     _writableState: 
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 0,
        prefinished: false,
        errorEmitted: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: false,
     destroyed: false,
     _bytesDispatched: 2563,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: undefined,
     _server: null,
     ssl: 
      TLSWrap {
        bytesRead: 700,
        _externalStream: {},
        fd: 73,
        _parent: [Object],
        _parentWrap: undefined,
        _secureContext: [Object],
        reading: true,
        owner: [Circular],
        onread: [Function: onread],
        writeQueueSize: 1,
        onhandshakestart: [Function],
        onhandshakedone: [Function],
        onocspresponse: [Function],
        onerror: [Function] },
     _requestCert: true,
     _rejectUnauthorized: true,
     parser: 
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': null,
        _headers: [],
        _url: '',
        _consumed: false,
        socket: [Circular],
        incoming: [Circular],
        outgoing: [Object],
        maxHeaderPairs: 2000,
        onIncoming: [Function: parserOnIncomingClient] },
     _httpMessage: 
      ClientRequest {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedHeader: [Object],
        _contentLength: 2232,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Circular],
        connection: [Circular],
        _header: 'POST /api/144447/store/ HTTP/1.1\r\nX-Sentry-Auth: Sentry sentry_version=5, sentry_timestamp=1493865130216, sentry_client=raven-node/1.1.4, sentry_key=a556c0165bc74435952c95dccc5938ec, sentry_secret=484978beb99f40208cb86610e66bead6\r\nContent-Type: application/octet-stream\r\nContent-Length: 2232\r\nHost: sentry.io\r\nConnection: close\r\n\r\n',
        _headers: [Object],
        _headerNames: [Object],
        _onPendingData: null,
        agent: [Object],
        socketPath: undefined,
        method: 'POST',
        path: '/api/144447/store/',
        _ended: false,
        parser: [Object],
        res: [Circular] },
     read: [Function],
     _consuming: true },
  _consuming: false,
  _dumped: false,
  req: 
   ClientRequest {
     domain: null,
     _events: { error: [Function], prefinish: [Function: requestOnPrefinish] },
     _eventsCount: 2,
     _maxListeners: undefined,
     output: [],
     outputEncodings: [],
     outputCallbacks: [],
     outputSize: 0,
     writable: true,
     _last: true,
     chunkedEncoding: false,
     shouldKeepAlive: false,
     useChunkedEncodingByDefault: true,
     sendDate: false,
     _removedHeader: { 'content-length': false },
     _contentLength: 2232,
     _hasBody: true,
     _trailer: '',
     finished: true,
     _headerSent: true,
     socket: 
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: null,
        npnProtocol: false,
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 10,
        connecting: false,
        _hadError: false,
        _handle: [Object],
        _parent: null,
        _host: 'sentry.io',
        _readableState: [Object],
        readable: true,
        domain: null,
        _maxListeners: undefined,
        _writableState: [Object],
        writable: true,
        allowHalfOpen: false,
        destroyed: false,
        _bytesDispatched: 2563,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: [Object],
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: [Object],
        _httpMessage: [Circular],
        read: [Function],
        _consuming: true },
     connection: 
      TLSSocket {
        _tlsOptions: [Object],
        _secureEstablished: true,
        _securePending: false,
        _newSessionPending: false,
        _controlReleased: true,
        _SNICallback: null,
        servername: null,
        npnProtocol: false,
        alpnProtocol: false,
        authorized: true,
        authorizationError: null,
        encrypted: true,
        _events: [Object],
        _eventsCount: 10,
        connecting: false,
        _hadError: false,
        _handle: [Object],
        _parent: null,
        _host: 'sentry.io',
        _readableState: [Object],
        readable: true,
        domain: null,
        _maxListeners: undefined,
        _writableState: [Object],
        writable: true,
        allowHalfOpen: false,
        destroyed: false,
        _bytesDispatched: 2563,
        _sockname: null,
        _pendingData: null,
        _pendingEncoding: '',
        server: undefined,
        _server: null,
        ssl: [Object],
        _requestCert: true,
        _rejectUnauthorized: true,
        parser: [Object],
        _httpMessage: [Circular],
        read: [Function],
        _consuming: true },
     _header: 'POST /api/144447/store/ HTTP/1.1\r\nX-Sentry-Auth: Sentry sentry_version=5, sentry_timestamp=1493865130216, sentry_client=raven-node/1.1.4, sentry_key=a556c0165bc74435952c95dccc5938ec, sentry_secret=484978beb99f40208cb86610e66bead6\r\nContent-Type: application/octet-stream\r\nContent-Length: 2232\r\nHost: sentry.io\r\nConnection: close\r\n\r\n',
     _headers: 
      { 'x-sentry-auth': 'Sentry sentry_version=5, sentry_timestamp=1493865130216, sentry_client=raven-node/1.1.4, sentry_key=a556c0165bc74435952c95dccc5938ec, sentry_secret=484978beb99f40208cb86610e66bead6',
        'content-type': 'application/octet-stream',
        'content-length': 2232,
        host: 'sentry.io' },
     _headerNames: 
      { 'x-sentry-auth': 'X-Sentry-Auth',
        'content-type': 'Content-Type',
        'content-length': 'Content-Length',
        host: 'Host' },
     _onPendingData: null,
     agent: 
      Agent {
        domain: null,
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        defaultPort: 443,
        protocol: 'https:',
        options: [Object],
        requests: {},
        sockets: [Object],
        freeSockets: {},
        keepAliveMsecs: 1000,
        keepAlive: false,
        maxSockets: Infinity,
        maxFreeSockets: 256,
        maxCachedSessions: 100,
        _sessionCache: [Object] },
     socketPath: undefined,
     method: 'POST',
     path: '/api/144447/store/',
     _ended: false,
     parser: 
      HTTPParser {
        '0': [Function: parserOnHeaders],
        '1': [Function: parserOnHeadersComplete],
        '2': [Function: parserOnBody],
        '3': [Function: parserOnMessageComplete],
        '4': null,
        _headers: [],
        _url: '',
        _consumed: false,
        socket: [Object],
        incoming: [Circular],
        outgoing: [Circular],
        maxHeaderPairs: 2000,
        onIncoming: [Function: parserOnIncomingClient] },
     res: [Circular] } }

@pbogdan
Copy link
Member

pbogdan commented May 7, 2017

You have a space character here johnramsden/nixos@e9446ad#diff-162a1061d291896411fa1ebeefa8c1fcR121 in between -- and replace which is breaking substitution.

@johnramsden
Copy link
Member Author

Oh jeez, that's better! Thanks for all your help @pbogdan!

@johnramsden johnramsden changed the title Cannot use keyring with custom package Cannot link to binary May 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants