diff --git a/.gitignore b/.gitignore index c22ee1e..4fd2111 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ coverage example/test example/tmp package-lock.json +.vs/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 7fa2ea8..a01f4a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,8 @@ script: - npm run coverage - cat coverage/lcov.info | lcov-server --upload https://lcov-server.gabrielcsapo.com node_js: - - "6" - - "8" + - "10" + - "12" os: - linux sudo: false diff --git a/tryitout.js b/.tryitout similarity index 82% rename from tryitout.js rename to .tryitout index 707a7f6..cf355f4 100644 --- a/tryitout.js +++ b/.tryitout @@ -9,7 +9,7 @@ module.exports = { body: `

${description}

-
+        
       const Server = require('node-git-server');
       const repo = new Server(path.resolve(__dirname, 'tmp'), {
           autoCreate: true,
@@ -31,5 +31,12 @@ module.exports = {
   },
   footer: `
        
Made with ☕️ by @gabrielcsapo
- ` + `, + template: 'landing', + output: './docs', + externals: [ + "./docs/krayon.css", + "./docs/krayon.min.js", + "./docs/main.js" + ] }; diff --git a/CHANGELOG.md b/CHANGELOG.md index 060b988..1d54091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,45 @@ +# 0.6.1 (03/03/2019) + +- Fixes bug with being able to overwrite git repos that a user doesn't have access to. @masasron + +# 0.6.0 (03/03/2019) + +- Augments the authenticate function declaration to accept an object as the first argument and a callback for the second. This allows us to make changes without having to cause breaking changes. + - Adds the ability to introspect on the header (fixes #49) + +# 0.5.1 (03/03/2019) + +- bump dependencies + - tap `^11.0.1` -> `^12.5.3` + - tryitout `^2.0.6` -> `^2.1.1` + +# 0.5.0 (11/27/2018) + +- adds `log` functionality for event streams and response streams + +# 0.4.3 (04/30/2018) + +- removes deprecated `Buffer` interface + +# 0.4.2 (12/07/2017) + +- adds https support + +# 0.4.1 (12/04/2017) + +- fixes type to be the same as the event names + +# 0.4.0 (12/03/2017) + +- [BREAKING] changes the interface for authentication to make it more flexible +- when error is sent back to client ensure error is string + +# 0.3.4 (11/10/2017) + +- updates duplex lib to fix cork, uncork and add some chaining +- adds extensive docs to Git, Util and Service +- adds named function to events to trace errors more easily + # 0.3.3 (11/05/2017) - Removes dependency on http-duplex package replacing w/ internal replacement lib diff --git a/README.md b/README.md index 3a86497..ec033c1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ > 🎡 A configurable git server written in Node.js +>> there be 🐲 here! The API's and functionality are still be cemented, anything before a 1.0.0 release will be subject to change. + [![Npm Version](https://img.shields.io/npm/v/node-git-server.svg)](https://www.npmjs.com/package/node-git-server) [![Build Status](https://travis-ci.org/gabrielcsapo/node-git-server.svg?branch=master)](https://travis-ci.org/gabrielcsapo/node-git-server) [![Coverage Status](https://lcov-server.gabrielcsapo.com/badge/github%2Ecom/gabrielcsapo/node-git-server.svg)](https://lcov-server.gabrielcsapo.com/coverage/github%2Ecom/gabrielcsapo/node-git-server) @@ -18,26 +20,135 @@ npm install node-git-server # Usage +## Simple + +```javascript +const path = require('path'); +const Server = require('node-git-server'); + +const repos = new Server(path.resolve(__dirname, 'tmp'), { + autoCreate: true +}); +const port = process.env.PORT || 7005; + +repos.on('push', (push) => { + console.log(`push ${push.repo}/${push.commit} (${push.branch})`); + push.accept(); +}); + +repos.on('fetch', (fetch) => { + console.log(`fetch ${fetch.commit}`); + fetch.accept(); +}); + +repos.listen(port, () => { + console.log(`node-git-server running at http://localhost:${port}`) +}); +``` + +then start up the node-git-server server... + +``` +$ node example/index.js +``` + +meanwhile... + +``` +$ git push http://localhost:7005/beep master +Counting objects: 356, done. +Delta compression using up to 2 threads. +Compressing objects: 100% (133/133), done. +Writing objects: 100% (356/356), 46.20 KiB, done. +Total 356 (delta 210), reused 355 (delta 210) +To http://localhost:7005/beep + * [new branch] master -> master +``` + +## Sending logs + +```javascript +const path = require('path'); +const Server = require('node-git-server'); + +const repos = new Server(path.resolve(__dirname, 'tmp'), { + autoCreate: true +}); +const port = process.env.PORT || 7005; + +repos.on('push', (push) => { + console.log(`push ${push.repo}/${push.commit} (${push.branch})`); + + repos.list((err, results) => { + push.log(' '); + push.log('Hey!'); + push.log('Checkout these other repos:'); + for(const repo of results) { + push.log(`- ${repo}`); + } + push.log(' '); + }); + + push.accept(); +}); + +repos.listen(port, () => { + console.log(`node-git-server running at http://localhost:${port}`) +}); +``` + +then start up the node-git-server server... + +``` +$ node example/index.js +``` + +meanwhile... + +``` +$ git push http://localhost:7005/beep master +Counting objects: 356, done. +Delta compression using up to 2 threads. +Compressing objects: 100% (133/133), done. +Writing objects: 100% (356/356), 46.20 KiB, done. +Total 356 (delta 210), reused 355 (delta 210) +remote: +remote: Hey! +remote: Checkout these other repos: +remote: - test.git +remote: +To http://localhost:7005/test + 77bb26e..22918d5 master -> master +``` + +### Authentication + ```javascript +const path = require('path'); const Server = require('node-git-server'); -const repo = new Server(path.resolve(__dirname, 'tmp'), { + +const repos = new Server(path.resolve(__dirname, 'tmp'), { autoCreate: true, - authenticate: (type, repo, username, password, next) => { - console.log(type, repo, username, password); - next(); + authenticate: ({type, repo, user}, next) => { + if(type == 'push') { + user((username, password) => { + console.log(username, password); + next(); + }); + } else { + next(); + } } }); const port = process.env.PORT || 7005; repos.on('push', (push) => { - console.log('push ' + push.repo + '/' + push.commit - + ' (' + push.branch + ')' - ); + console.log(`push ${push.repo}/${push.commit} (${push.branch})`); push.accept(); }); repos.on('fetch', (fetch) => { - console.log('fetch ' + fetch.commit); + console.log(`fetch ${fetch.commit}`); fetch.accept(); }); @@ -65,6 +176,22 @@ To http://localhost:7005/beep * [new branch] master -> master ``` +# Example + +Running the following command will start up a simple http server: + +``` +node example/index.js +``` + +If you want to try using https run the following + +``` +node example/index.js --https +``` + +> When running https with self-signed certs there are two ways to override the git-clients behavior using `git config http.sslVerify false` or `git config --global http.sslCAInfo /path/to/cert.pem` + For more information please visit the [docs](http://www.gabrielcsapo.com/node-git-server/code/index.html) # Philosophy diff --git a/docs/code/Git.html b/docs/code/Git.html index b13e5a0..ec8f958 100644 --- a/docs/code/Git.html +++ b/docs/code/Git.html @@ -22,7 +22,7 @@
@@ -53,7 +53,7 @@

-

new Git(repoDir, options) → {Git}

+

new Git(repoDir, options)

@@ -65,7 +65,7 @@

new GitSource:
@@ -105,49 +105,7 @@

new Git -

events

repos.on('push', function (push) { ... }

Emitted when somebody does a git push to the repo.

-

Exactly one listener must call push.accept() or push.reject(). If there are - no listeners, push.accept() is called automatically.

-

push is an http duplex object (see below) with these extra properties: -push.repo -push.commit -push.branch

-

repos.on('tag', function (tag) { ... }

Emitted when somebody does a git push --tags to the repo.

-

Exactly one listener must call tag.accept() or tag.reject(). If there are - no listeners, tag.accept() is called automatically.

-

tag is an http duplex object (see below) with these extra properties: -tag.repo -tag.commit -tag.version

-

repos.on('fetch', function (fetch) { ... }

Emitted when somebody does a git fetch to the repo (which happens whenever you - do a git pull or a git clone).

-

Exactly one listener must call fetch.accept() or fetch.reject(). If there are - no listeners, fetch.accept() is called automatically.

-

fetch is an http duplex objects (see below) with these extra properties: -fetch.repo -fetch.commit

-

repos.on('info', function (info) { ... }

Emitted when the repo is queried for info before doing other commands.

-

Exactly one listener must call info.accept() or info.reject(). If there are - no listeners, info.accept() is called automatically.

-

info is an http duplex object (see below) with these extra properties: -info.repo

-

repos.on('head', function (head) { ... }

Emitted when the repo is queried for HEAD before doing other commands.

-

Exactly one listener must call head.accept() or head.reject(). If there are - no listeners, head.accept() is called automatically.

-

head is an http duplex object (see below) with these extra properties: -head.repo

-

push.on('response', function(response, done) { ... })

Emitted when node-git-server creates a response stream that will be sent to the git client on the other end.

-

This should really only be used if you want to send verbose or error messages to the remote git client.

-

response is a writable stream that can accept buffers containing git packfile sidechannel transfer protocol encoded strings. done is a callback that must be called when you want to end the response.

-

If you create a response listener then you must either call the done function or execute the following end sequence when you want to end the response:

-
   response.queue(new Buffer('0000'))
-   response.queue(null)

If you never use the response event then the above data will be sent by default. Binding a listener to the response event will prevent the end sequence those from being sent, so you must send them yourself after sending any other messages.

-

http duplex objects

The arguments to each of the events 'push', 'fetch', 'info', and 'head' are http duplex that act as both http - server request and http server response objects so you can pipe to and from them.

-

For every event if there are no listeners dup.accept() will be called - automatically.

-

dup.accept()

Accept the pending request.

-

dup.reject()

Reject the pending request.

+

Handles invoking the git-*-pack binaries

@@ -313,13 +271,13 @@
Properties
-

a function that has the following arguments (repo, username, password, next) and will be called when a request comes through if set

-
 authenticate: (type, repo, username, password, next) => {
+            

a function that has the following arguments ({ type, repo, username, password, headers }, next) and will be called when a request comes through if set

+
 authenticate: ({ type, repo, username, password, headers }, next) => {
    console.log(type, repo, username, password);
    next();
  }
  // alternatively you can also pass authenticate a promise
- authenticate: (type, repo, username, password, next) => {
+ authenticate: ({ type, repo, username, password, headers }, next) => {
    console.log(type, repo, username, password);
    return new Promise((resolve, reject) => {
     if(username === 'foo') {
@@ -360,8 +318,7 @@ 
Properties
-

If opts.checkout is true, create and expected checked-out repos instead of - bare repos

+

If opts.checkout is true, create and expected checked-out repos instead of bare repos

@@ -388,28 +345,57 @@
Properties
-
Returns:
+ + + +
+ + +

Extends

-
-
- Type -
-
+
    +
  • EventEmitter
  • +
+ + + + + + + + + + + + + + + +

Methods

+ -Git + + -
-
+

(static) close()

+ + +
+ + +
Source:
+
- @@ -417,7 +403,7 @@
Returns:
- + @@ -428,35 +414,103 @@
Returns:
- - + + + + + + + +
-
-
+ +
+

closes the server instance

+
+ + + + + + + + + + + +
Parameters:
-

- Git -

+ + + + + + + + + + + + + + + + - -
-
+
+ + + + + + + + + + + + +
TypeDescription
+ + +Promise + + + +

will resolve or reject when the server closes or fails to close.

+ + + + + + + + + + + + + + + + + -

new Git()

+

(static) create(repo, callbackopt)

@@ -468,7 +522,7 @@

new GitSource:
@@ -507,6 +561,12 @@

new Git +

Create a new bare repository repoName in the instance repository directory.

+ + + + @@ -515,32 +575,140 @@

new GitParameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
repo + + +String + + + + + +

the name of the repo

callback + + +function + + + + + + <optional>
+ + + + + +

Optionally get a callback cb(err) to be notified when the repository was created.

+ + + + + + + + + + + + + + + + + + + +

(static) exists(repo, callbackopt)

- + + + +
+ + +
Source:
+
+ + + + + + + + + @@ -551,6 +719,2294 @@

new Git + + + + + +
+

Find out whether repoName exists in the callback cb(exists).

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
repo + + +String + + + + + + + + + +

name of the repo

callback + + +function + + + + + + <optional>
+ + + + + +

function to be called when finished

+ + + + + + + + + + + + + + + + + + + + + +

(static) handle(req, res)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Handle incoming HTTP requests with a connect-style middleware

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
req + + +Object + + + +

http request object

res + + +Object + + + +

http response object

+ + + + + + + + + + + + + + + + + + + + + +

(static) list(callback)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Get a list of all the repositories

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + +

function to be called when repositories have been found function(error, repos)

+ + + + + + + + + + + + + + + + + + + + + +

(static) listen(port, optionsopt, callback) → {Git}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

starts a git server on the given port

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
port + + +Number + + + + + + + + + +

the port to start the server on

options + + +Object + + + + + + <optional>
+ + + + + +

the options to add extended functionality to the server

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
type + + +String + + + + + + <optional>
+ + + + + +

this is either https or http (the default is http)

key + + +Buffer +| + +String + + + + + + + + + +

the key file for the https server

cert + + +Buffer +| + +String + + + + + + + + + +

the cert file for the https server

+ +
callback + + +function + + + + + + + + + +

the function to call when server is started or error has occured

+ + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • the Git instance, useful for chaining
  • +
+
+ + + +
+
+ Type +
+
+ +Git + + +
+
+ + + + + + + + + +

(static) mkdir(dir, callbackopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Create a subdirectory dir in the repo dir with a callback cb(err).

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
dir + + +String + + + + + + + + + +

directory name

callback + + +function + + + + + + <optional>
+ + + + + +

callback to be called when finished

+ + + + + + + + + + + + + + + + + + + + + + +

Events

+ + + + + + +

fetch

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
fetch + + +HttpDuplex + + + +

an http duplex object (see below) with these extra properties:

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
repo + + +String + + + +

the string that defines the repo

commit + + +String + + + +

the string that defines the commit sha

+ +
+ + + + + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Example
+ +
repos.on('fetch', function (fetch) { ... }
+
+    Emitted when somebody does a `git fetch` to the repo (which happens whenever you
+    do a `git pull` or a `git clone`).
+
+    Exactly one listener must call `fetch.accept()` or `fetch.reject()`. If there are
+    no listeners, `fetch.accept()` is called automatically.
+ + + + + + + + + + + + + + + + + + + + + + + +

head

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
head + + +HttpDuplex + + + +

an http duplex object (see below) with these extra properties:

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
repo + + +String + + + +

the string that defines the repo

+ +
+ + + + + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Example
+ +
repos.on('head', function (head) { ... }
+
+    Emitted when the repo is queried for HEAD before doing other commands.
+
+    Exactly one listener must call `head.accept()` or `head.reject()`. If there are
+    no listeners, `head.accept()` is called automatically.
+ + + + + + + + + + + + + + + + + + + + + + + +

info

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
info + + +HttpDuplex + + + +

an http duplex object (see below) with these extra properties:

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
repo + + +String + + + +

the string that defines the repo

+ +
+ + + + + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Example
+ +
repos.on('info', function (info) { ... }
+
+    Emitted when the repo is queried for info before doing other commands.
+
+    Exactly one listener must call `info.accept()` or `info.reject()`. If there are
+    no listeners, `info.accept()` is called automatically.
+ + + + + + + + + + + + + + + + + + + + + + + +

info

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
info + + +HttpDuplex + + + +

an http duplex object (see below) with these extra properties:

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
repo + + +String + + + +

the string that defines the repo

+ +
+ + + + + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Example
+ +
repos.on('info', function (info) { ... }
+
+    Emitted when the repo is queried for info before doing other commands.
+
+    Exactly one listener must call `info.accept()` or `info.reject()`. If there are
+    no listeners, `info.accept()` is called automatically.
+ + + + + + + + + + + + + + + + + + + + + + + +

push

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
push + + +HttpDuplex + + + +

is a http duplex object (see below) with these extra properties

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
repo + + +String + + + +

the string that defines the repo

commit + + +String + + + +

the string that defines the commit sha

branch + + +String + + + +

the string that defines the branch

+ +
+ + + + + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Example
+ +
repos.on('push', function (push) { ... }
+
+    Emitted when somebody does a `git push` to the repo.
+
+    Exactly one listener must call `push.accept()` or `push.reject()`. If there are
+    no listeners, `push.accept()` is called automatically.
+ + + + + + + + + + + + + + + + + + + + + + + +

tag

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
tag + + +HttpDuplex + + + +

an http duplex object (see below) with these extra properties:

+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
repo + + +String + + + +

the string that defines the repo

commit + + +String + + + +

the string that defines the commit sha

version + + +String + + + +

the string that defines the repo

+ +
+ + + + + + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Example
+ +
repos.on('tag', function (tag) { ... }
+
+    Emitted when somebody does a `git push --tags` to the repo.
+    Exactly one listener must call `tag.accept()` or `tag.reject()`. If there are
+    No listeners, `tag.accept()` is called automatically.
+ + + + + + + + + + + + + + + + + + + +

diff --git a/docs/code/HttpDuplex.html b/docs/code/HttpDuplex.html index 76c7f6f..0aa4144 100644 --- a/docs/code/HttpDuplex.html +++ b/docs/code/HttpDuplex.html @@ -22,7 +22,7 @@
@@ -266,7 +266,7 @@

Members

-

(readonly) headers :object

+

(readonly) headers :Object

@@ -333,7 +333,7 @@
Type:
  • -object +Object
  • @@ -426,7 +426,7 @@
    Type:
    -

    (readonly) method :string

    +

    (readonly) method :String

    @@ -495,7 +495,7 @@
    Type:
    • -string +String
    • @@ -513,7 +513,7 @@
      Example
      -

      (readonly) readable :boolean

      +

      (readonly) readable :Boolean

      @@ -573,7 +573,7 @@
      Type:
      • -boolean +Boolean
      • @@ -646,8 +646,8 @@

        req -

        A IncomingMessage created by http.Server or http.ClientRequest usually passed as the -first parameter to the 'request' and 'response' events. Implements Readable Stream interface +

        A IncomingMessage created by http.Server or http.ClientRequest usually passed as the +first parameter to the 'request' and 'response' events. Implements Readable Stream interface but may not be a decendant thereof.

@@ -833,7 +833,7 @@
Type:
-

statusCode :number

+

statusCode :Number

@@ -905,7 +905,7 @@
Type: