# ssb-git-repo

Host git repos in [secure-scuttlebutt][]

## Example

```js
var ssbGit = require('ssb-git-repo')
var repoId = '%CBeVWA9eYt6OhJDXFtqas6kWb5LwaJxYtfwDazKvh4U=.sha256'

// get a single repo:
ssbGit.getRepo(sbot, repoId, function (err, repo) {
  if (err) throw err
  // do something with the repo
})
```

## API

#### `ssbGit.createRepo(sbot[, options], cb(err, repo))`

Create a repo. Publishes a message announcing the new repo.

- `sbot`: a [scuttlebot][] or [ssb-client][] object
- `options.upstream` (`ssbGit.Repo` or MsgId): upstream repo (of which
  the new repo will be a fork)
- `options.name` (string): name to give the repo
- `options.live`: keep the repo updated as changes are pushed to it
- `options.output`: stream for logging stuff to
- `options.recps`: feed ids to encrypt the repo to. Makes the repo private.
- `cb`: function called when the repo is created
- `err`: error creating the repo, if any
- `repo`: `ssbGit.Repo` object for the new repo

#### `ssbGit.getRepo(sbot, msgOrId[, options], cb(err, repo))`

Get a repo.

- `sbot`: a [scuttlebot][] or [ssb-client][] object
- `msgOrId`: SSB message that started the repo, or the ID of it
- `options.live`: keep the repo updated as changes are pushed to it
- `options.output`: stream for logging stuff to
- `cb`: function called when the repo is retrieved
- `err`: error retrieving the repo, if any
- `repo`: `ssbGit.Repo` object for the retrieved repo

#### `ssbGit.repos(sbot, options): source(repo)`

Get repos from the feed

- `sbot`: a [scuttlebot][] or [ssb-client][] object
- `options`: options to pass to `sbot.createFeedStream`
- `repo`: `ssbGit.Repo` object

#### `ssbGit.Repo`

An [abstract-pull-git-repo][]-compliant git repo object.
Additional methods and properties:

#### `repo.private: boolean`

Whether the repo is private (true), or public (false)

#### `repo.recps: [feedId...]?`

Feed ids that have access to the repo if it is private.

#### `repo.close(cb(err))`

Close the repo's update stream.

- `cb`: function called when the repo's stream is closed
- `err`: error closing the repo, if any

#### `repo.getHead(cb(err, head))`

Get the repo's HEAD, i.e. the "default branch" ref, e.g. `"refs/heads/master"

#### `repo.hasObjectQuick(hash) : has`

Check for the presence of a commit hash, with possible false negatives.

- `hash` (sha1): the commit id to check
- `has` (boolean): true if the commit is present

This will only show an object as present if it was pushed in ssb-git-repo
>= v1.9.0.

#### `repo.getLatestAvailableRev(ref, timeout, cb(err, rev, numSkipped))`

Get the latest revision for a ref that can be rendered. Try to retrieve
the latest revision for a ref, and after a timeout try to retrieve the
next latest, etc.

- `ref` (string): name of ref, branch or tag to look up
- `rev` (sha1):  id of the latest rev that is available
- `numSkipped` (int): number of unavailable revs skipped

[abstract-pull-git-repo]: https://github.com/clehner/abstract-pull-git-repo
[ssb-client]: https://github.com/ssbc/ssb-client
[scuttlebot]: https://github.com/ssbc/scuttlebot
[secure-scuttlebutt]: https://github.com/ssbc/secure-scuttlebutt
[pull-stream]: https://github.com/dominictarr/pull-stream

### Schema

#### type: git-repo

```js
{ type: 'git-repo' }
```

Creates a git repo. Note that you can actually push git objects to any message
in your feed, but the `git-repo` type is here to declare that a message will be
for a git repo. It may have properties added later.

#### type: git-update

```js
{
  type: 'git-update',
  repo: MsgId,
  repoBranch: [ MsgId ]?,
  refsBranch: [ MsgId ]?,
  refs: { <ref>: String|null }?,
  packs: [ BlobLink ]?,
  indexes: [ BlobLink ]?,
  head: string?,
  commits: [ {
    sha1: String,
    title: String,
    body: String?,
    parents: [ String ]?,
  } ]?,
  tags: [ {
    sha1: String,
    object: String,
    type: String?,
    tag: String?,
  } ]?,
  commits_more: Number?,
  tags_more: Number?,
  num_objects: Number?,
  object_ids: [ String ]?,
}
```

Updates a repo. Published as a result of `git push`.

- `repo`: id of a message (expected of type `git-repo`) identifying the repo
- `refsBranch`: ids of latest concurrent previous git-update messages
  not already mentioned in `repoBranch`. Use to indicate causal order of
  updates to refs.
- `repoBranch`: ids of latest git-update messages containing git
  objects that this message's packfile(s) depend on. Use for packfile
  construction during fetch.
- `refs`: updates to the repo's refs. a map of ref names to git sha1 hashes.
  e.g. `{ 'refs/heads/master': commitId }`
- `packs`: links to git packfiles being added to the repo
- `indexes`: links to index files for the packfiles in `packs`
- `head`: value of the HEAD symref, i.e. the default branch, e.g.
  `"refs/heads/master"`
- `commits`: array of info about commits that are included in `packs`
- `commits_more`: number of commits included in `packs` but not in `commits`
- `tags`: array of info about tags that are included in `packs`
  - `tag.type`: type of the git object pointed to by the tag, e.g. "commit"
  - `tag.object`: id of the git object pointed to by the tag
  - `tag.tag`: name of the tag
  - `tag.sha1`: id of the tag
- `tags_more`: number of tags included in `packs` but not in `tags`
- `num_objects`: number of objects included in `packs`
- `object_ids`: sha1 hashes of git objects included in `packs`, other than
  commit ids mentioned in `commits`. If not all can be included in the array
  because of the message size limit, omit this property instead of truncating
  the array.

## License

Copyright (c) 2016 Charles Lehner

Usage of the works is permitted provided that this instrument is
retained with the works, so that any entity that uses the works is
notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
