Coder Social home page Coder Social logo

grit-http's Introduction

GritHttp

GritHttp is a Sinatra application that provides a web JSON-based API to git repositories.

Git support is powered by Grit ruby library.

The main purpose of this application is to serve git objects data via simple api interface. If you're hosting git repositories on your own server this tool might be useful to provide an access to a third-party apps.

Installation

The current state is not stable yet, but you can install this application by cloning the official git repo:

$ git clone git://github.com/sosedoff/grit-http.git
$ cd grit-http
$ bundle install

Configuration

Be default all configuration files are located in config/ folder under the app's root path.

There is a sample config file - config.yml.sample - where you can find more details and possible options.

Sample configuration:

protection: true
cache: false
api_keys:
  - "SAMPLE_API_KEY"
repositories:
  name: /path/to/repository

Options:

  • protection - Enable/disable API keys usage.
  • cache - Enable/disable caching
  • api_keys - List of your API keys. You can add as many as you want
  • repositories - List of full paths to your repositories. Each repository should have an alias, which is going to be used in requests.

Deployment

The easiest way to get it up and running is to use Thin:

$ cd grit-http
$ thin start -e production

Passenger Phusion + Nginx

Sample configuration:

server {
  listen 80;
  server_name git.yourhost.com
  charset utf-8;
  passenger_enabled on;
  rack_env production;
  root /path/to/app/public;
}

Passenger Phusion + Nginx (Subroute)

If you already have an application deployed with passenger, its really easy to add another subroute to the app.

Just symlink grit-http's public folder into your current app's public folder. Name of this folder should be the same as you use in subroute.

server {
  listen 80;
  server_name yourhost.com
  charset utf-8;
  passenger_enabled on;
  passenger_base_uri /git;
  rails_env production;
  root /path/to/your/existing/app;
}

Unicorn + Nginx

This section is coming soon.

API Usage

API allowes you to make only GET requests, it is a read-only resource. It returns each response in JSON mode and UTF-8 encoding (except raw method).

Each response (failed and successful) from server has a structure:

{
  "result": true,
  "data": {}
}

Fields:

  • result - Indicates if request was successful. (true/false)
  • data - Primary container for api response.

If configuration option "protection" is set to true, all requests should have a "api_key" parameter added.

Unprotected request:

curl -i "http://yourhost.com/"

Protected request:

curl -i "http://yourhost.com/?api_key=KEY"

Get repositories list

GET /repositories

Response:

{
  "result": true,
  "data": {
    "repositories": [
      "sinatra"
    ]
  }
}

Get repository information

GET /repository?repo=sinatra

Response:

{
  "result": true,
  "data": {
    "name": "sinatra",
    "bare": false,
    "filesize": 2035712
  }
}

Get repository branches (heads)

GET /heads?repo=sinatra

Response:

{
  "result": true,
  "data": [
    {
      "name": "master",
      "commit": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc"
    }
  ]
}

Get repository tags

GET /tags?repo=sinatra

Response:

{
  "result": true,
  "data": [
    {
      "name": "v1.3.0.e",
      "commit": "b5a310437e58a4d198216a41d76df60ef8186ac7"
    },
    {
      "name": "v1.3.0.d",
      "commit": "e9e6e737f913287340a82bdfd4fbaa47591d270f"
    }
  ]
}

Get repository refs (heads + tags)

GET /refs?repo=sinatra

Response:

{
  "result": true,
  "data": [
    {
      "name": "0.3.x",
      "commit": "4aefc7d024837e4a947fa978d621b4f019aeda1d"
    },
    {
      "name": "origin/0.3.x",
      "commit": "4aefc7d024837e4a947fa978d621b4f019aeda1d"
    }
  ]
}

Repository authors

GET /authors?repo=sinatra

Response:

{
  "result": true,
  "data": [
    {
      "name": "Konstantin Haase",
      "commits": 733,
      "position": 1
    },
    {
      "name": "Ryan Tomayko",
      "commits": 325,
      "position": 2
    }
  ]
}

Get repository commits

GET /commits?repo=sinatra

Options:

  • head - Git head to use (default: master)
  • path - Path to fetch commits from
  • max_count - Limit amount of commits (default: 10, max: 25)
  • skip - Amount of commits to skip (default: 0)

Response:

{
  "result": true,
  "data": {
    "head": "master",
    "path": null,
    "commits": [
      {
        "id": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc",
        "parents": [
          {
            "id": "9eb0dfe7dd0eaa48c5c55b6a1193f0c86f53f020"
          },
          {
            "id": "dd6fd9953b1a3568266e6a226c53093fb08a6817"
          }
        ],
        "tree": "a43281fdbc23304dcc7891321e4350e07c8cde41",
        "message": "Merge branch 'master' of github.com:sinatra/sinatra",
        "author": {
          "name": "Konstantin Haase",
          "email": "[email protected]",
          "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
        },
        "committer": {
          "name": "Konstantin Haase",
          "email": "[email protected]",
          "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
        },
        "authored_date": "2011-06-22T12:26:55-05:00",
        "committed_date": "2011-06-22T12:26:55-05:00"
      }
    ]
  }
}

Get a single commit

GET /commit?repo=sinatra&id=a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc

Response:

{
  "result": true,
  "data": {
    "head": "master",
    "path": null,
    "stats": {
      "id": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc",
      "additions": 0,
      "deletions": 0,
      "total": 0,
      "files": [

      ]
    },
    "diffs": [
      {
        "a_path": "lib/sinatra/base.rb",
        "b_path": "lib/sinatra/base.rb",
        "deleted_file": false,
        "new_file": false,
        "content": "--- a/lib/sinatra/base.rb\n+++ b/lib/sinatra/base.rb\n@@ -189,6 +189,8 @@\n       if filename\n         params = '; filename=\"%s\"' % File.basename(filename)\n         response['Content-Disposition'] << params\n+        ext = File.extname(filename)\n+        content_type(ext) unless response['Content-Type'] or ext.empty?\n       end\n     end\n "
      },
      {
        "a_path": "test/helpers_test.rb",
        "b_path": "test/helpers_test.rb",
        "deleted_file": false,
        "new_file": false,
        "content": "--- a/test/helpers_test.rb\n+++ b/test/helpers_test.rb\n@@ -576,6 +576,45 @@\n     end\n   end\n \n+  describe 'attachment' do\n+    def attachment_app(filename=nil)\n+      mock_app {       \n+        get '/attachment' do\n+          attachment filename\n+          response.write(\"<sinatra></sinatra>\")\n+        end\n+      }\n+    end\n+    \n+    it 'sets the Content-Type response header' do\n+      attachment_app('test.xml')\n+      get '/attachment'\n+      assert_equal 'application/xml;charset=utf-8', response['Content-Type']\n+      assert_equal '<sinatra></sinatra>', body\n+    end \n+    \n+    it 'sets the Content-Type response header without extname' do\n+      attachment_app('test')\n+      get '/attachment'\n+      assert_equal 'text/html;charset=utf-8', response['Content-Type']\n+      assert_equal '<sinatra></sinatra>', body   \n+    end\n+    \n+    it 'sets the Content-Type response header without extname' do\n+      mock_app do\n+        get '/attachment' do\n+          content_type :atom\n+          attachment 'test.xml'\n+          response.write(\"<sinatra></sinatra>\")\n+        end\n+      end\n+      get '/attachment'\n+      assert_equal 'application/atom+xml', response['Content-Type']\n+      assert_equal '<sinatra></sinatra>', body   \n+    end\n+    \n+  end\n+\n   describe 'send_file' do\n     setup do\n       @file = File.dirname(__FILE__) + '/file.txt'"
      }
    ],
    "commit": {
      "id": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc",
      "parents": [
        {
          "id": "9eb0dfe7dd0eaa48c5c55b6a1193f0c86f53f020"
        },
        {
          "id": "dd6fd9953b1a3568266e6a226c53093fb08a6817"
        }
      ],
      "tree": "a43281fdbc23304dcc7891321e4350e07c8cde41",
      "message": "Merge branch 'master' of github.com:sinatra/sinatra",
      "author": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "committer": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "authored_date": "2011-06-22T12:26:55-05:00",
      "committed_date": "2011-06-22T12:26:55-05:00"
    }
  }
}

Get commit diffs

GET /commit/diff?repo=sinatra&id=a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc

Response:

{
  "result": true,
  "data": {
    "head": "master",
    "diff": [
      {
        "a_path": "lib/sinatra/base.rb",
        "b_path": "lib/sinatra/base.rb",
        "deleted_file": false,
        "new_file": false,
        "content": "--- a/lib/sinatra/base.rb\n+++ b/lib/sinatra/base.rb\n@@ -189,6 +189,8 @@\n       if filename\n         params = '; filename=\"%s\"' % File.basename(filename)\n         response['Content-Disposition'] << params\n+        ext = File.extname(filename)\n+        content_type(ext) unless response['Content-Type'] or ext.empty?\n       end\n     end\n "
      },
      {
        "a_path": "test/helpers_test.rb",
        "b_path": "test/helpers_test.rb",
        "deleted_file": false,
        "new_file": false,
        "content": "--- a/test/helpers_test.rb\n+++ b/test/helpers_test.rb\n@@ -576,6 +576,45 @@\n     end\n   end\n \n+  describe 'attachment' do\n+    def attachment_app(filename=nil)\n+      mock_app {       \n+        get '/attachment' do\n+          attachment filename\n+          response.write(\"<sinatra></sinatra>\")\n+        end\n+      }\n+    end\n+    \n+    it 'sets the Content-Type response header' do\n+      attachment_app('test.xml')\n+      get '/attachment'\n+      assert_equal 'application/xml;charset=utf-8', response['Content-Type']\n+      assert_equal '<sinatra></sinatra>', body\n+    end \n+    \n+    it 'sets the Content-Type response header without extname' do\n+      attachment_app('test')\n+      get '/attachment'\n+      assert_equal 'text/html;charset=utf-8', response['Content-Type']\n+      assert_equal '<sinatra></sinatra>', body   \n+    end\n+    \n+    it 'sets the Content-Type response header without extname' do\n+      mock_app do\n+        get '/attachment' do\n+          content_type :atom\n+          attachment 'test.xml'\n+          response.write(\"<sinatra></sinatra>\")\n+        end\n+      end\n+      get '/attachment'\n+      assert_equal 'application/atom+xml', response['Content-Type']\n+      assert_equal '<sinatra></sinatra>', body   \n+    end\n+    \n+  end\n+\n   describe 'send_file' do\n     setup do\n       @file = File.dirname(__FILE__) + '/file.txt'"
      }
    ]
  }
}

Get commit payload

GET /commit/payload?repo=sinatra&id=a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc

Response:

{
  "result": true,
  "data": {
    "repository": "sinatra",
    "head": "master",
    "commits": {
      "id": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc",
      "message": "Merge branch 'master' of github.com:sinatra/sinatra",
      "timestamp": "2011-06-22T12:26:55-05:00",
      "author": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "added": [

      ],
      "removed": [

      ],
      "modified": [
        "lib/sinatra/base.rb",
        "test/helpers_test.rb"
      ]
    }
  }
}

Get commits count

GET /commits_count?repo=sinatra

Response:

{
  "result": true,
  "data": {
    "count": 1547
  }
}

Get commits stats by dates

GET /commits_stats?repo=sinatra&days=5

Options:

  • days - Number of days from today (default: 30)

Response:

{
  "result": true,
  "data": {
    "2011-06-20": 0,
    "2011-06-21": 0,
    "2011-06-22": 2,
    "2011-06-23": 0,
    "2011-06-24": 0,
    "2011-06-25": 0
  }
}

Get commits diff

GET /compare?repo=sinatra&obj_from=ec1b83d566c888d9d53d54b262def820f00834cb&obj_to=e9de3248fb4e86a9cd6318c6a6e284c7db101df3

Response:

{
  "result": true,
  "data": {
    "commits": [
      {
        "id": "e9de3248fb4e86a9cd6318c6a6e284c7db101df3",
        "parents": [
          {
            "id": "ec1b83d566c888d9d53d54b262def820f00834cb"
          }
        ],
        "tree": "85a051f3b4bf41fd439138f1938ddc27124f1e30",
        "message": "add failing test for attachment",
        "author": {
          "name": "nashby",
          "email": "[email protected]",
          "gravatar": "608b32640d0fca097b40bc6a28cadc5f"
        },
        "committer": {
          "name": "nashby",
          "email": "[email protected]",
          "gravatar": "608b32640d0fca097b40bc6a28cadc5f"
        },
        "authored_date": "2011-06-17T14:57:20-05:00",
        "committed_date": "2011-06-17T14:57:20-05:00"
      }
    ],
    "diff": [
      {
        "a_path": "test/helpers_test.rb",
        "b_path": "test/helpers_test.rb",
        "deleted_file": false,
        "new_file": false,
        "content": "--- a/test/helpers_test.rb\n+++ b/test/helpers_test.rb\n@@ -593,6 +593,12 @@ class HelpersTest < Test::Unit::TestCase\n       assert_equal '<sinatra></sinatra>', body\n     end \n     \n+    it 'sets the Content-Type response header without extname' do\n+      attachment_app('test')\n+      get '/attachment'\n+      assert_equal '<sinatra></sinatra>', body   \n+    end\n+    \n   end\n \n   describe 'send_file' do"
      }
    ]
  }
}

Get a tree

GET /tree?repo=sinatra&path=lib/&history=true

Options:

  • path - Tree path (default: root)
  • history - Include last commit information for the tree items (default: false)

Response:

{
  "result": true,
  "data": {
    "head": "master",
    "path": "lib/",
    "commit": {
      "id": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc",
      "parents": [
        {
          "id": "9eb0dfe7dd0eaa48c5c55b6a1193f0c86f53f020"
        },
        {
          "id": "dd6fd9953b1a3568266e6a226c53093fb08a6817"
        }
      ],
      "tree": "a43281fdbc23304dcc7891321e4350e07c8cde41",
      "message": "Merge branch 'master' of github.com:sinatra/sinatra",
      "author": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "committer": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "authored_date": "2011-06-22T12:26:55-05:00",
      "committed_date": "2011-06-22T12:26:55-05:00"
    },
    "tree": [
      {
        "id": "b05028060f4c1be860518a55c85404928298f3ee",
        "type": "tree",
        "name": "lib/sinatra",
        "mode": "040000",
        "filesize": null,
        "commit": {
          "id": "2b31a86de07c4ef80faf22bbb8f3aa21bdea8577",
          "parents": [
            {
              "id": "e9de3248fb4e86a9cd6318c6a6e284c7db101df3"
            }
          ],
          "tree": "a6642f18a7cac601fbf1cb8e311a6fd3f8dcaa9b",
          "message": "fix failing test for attachment",
          "author": {
            "name": "nashby",
            "email": "[email protected]",
            "gravatar": "608b32640d0fca097b40bc6a28cadc5f"
          },
          "committer": {
            "name": "nashby",
            "email": "[email protected]",
            "gravatar": "608b32640d0fca097b40bc6a28cadc5f"
          },
          "authored_date": "2011-06-18T03:47:50-05:00",
          "committed_date": "2011-06-18T03:47:50-05:00"
        }
      },
      {
        "id": "71b122d1af6997f89ddb05ada1d1ea9821fa87fc",
        "type": "blob",
        "name": "lib/sinatra.rb",
        "mode": "100644",
        "filesize": 167,
        "commit": {
          "id": "3ef8eedef257b513f531dd48bfedcbc8df8a622b",
          "parents": [
            {
              "id": "0067232e1f75c02b9ea51bba2ca5e5fb3b7ae070"
            }
          ],
          "tree": "d65d452219fab096c381afc6872b80c73daaa30d",
          "message": "Deprecate use_in_file_templates!\n\nUse enable :inline_templates instead",
          "author": {
            "name": "Simon Rozet",
            "email": "[email protected]",
            "gravatar": "8cf17bf55c4d16cf52480619bb0b6c92"
          },
          "committer": {
            "name": "Simon Rozet",
            "email": "[email protected]",
            "gravatar": "8cf17bf55c4d16cf52480619bb0b6c92"
          },
          "authored_date": "2009-12-18T19:07:01-06:00",
          "committed_date": "2009-12-22T21:40:43-06:00"
        }
      }
    ]
  }
}

Get a tree history

GET /tree_history?repo=sinatra&path=lib/

Options:

  • path - Tree path (default: root)

Response:

{
  "result": true,
  "data": {
    "b05028060f4c1be860518a55c85404928298f3ee": {
      "id": "2b31a86de07c4ef80faf22bbb8f3aa21bdea8577",
      "parents": [
        {
          "id": "e9de3248fb4e86a9cd6318c6a6e284c7db101df3"
        }
      ],
      "tree": "a6642f18a7cac601fbf1cb8e311a6fd3f8dcaa9b",
      "message": "fix failing test for attachment",
      "author": {
        "name": "nashby",
        "email": "[email protected]",
        "gravatar": "608b32640d0fca097b40bc6a28cadc5f"
      },
      "committer": {
        "name": "nashby",
        "email": "[email protected]",
        "gravatar": "608b32640d0fca097b40bc6a28cadc5f"
      },
      "authored_date": "2011-06-18T03:47:50-05:00",
      "committed_date": "2011-06-18T03:47:50-05:00"
    },
    "71b122d1af6997f89ddb05ada1d1ea9821fa87fc": {
      "id": "3ef8eedef257b513f531dd48bfedcbc8df8a622b",
      "parents": [
        {
          "id": "0067232e1f75c02b9ea51bba2ca5e5fb3b7ae070"
        }
      ],
      "tree": "d65d452219fab096c381afc6872b80c73daaa30d",
      "message": "Deprecate use_in_file_templates!\n\nUse enable :inline_templates instead",
      "author": {
        "name": "Simon Rozet",
        "email": "[email protected]",
        "gravatar": "8cf17bf55c4d16cf52480619bb0b6c92"
      },
      "committer": {
        "name": "Simon Rozet",
        "email": "[email protected]",
        "gravatar": "8cf17bf55c4d16cf52480619bb0b6c92"
      },
      "authored_date": "2009-12-18T19:07:01-06:00",
      "committed_date": "2009-12-22T21:40:43-06:00"
    }
  }
}

Get a blob

GET /blob?repo=sinatra&path=lib/sinatra.rb

Options:

  • path - Blob path (required)
  • head - Use this branch to get blob

Response:

{
  "result": true,
  "data": {
    "head": "master",
    "commit": {
      "id": "a6f6a147bfe3a9d7cd05f8e06212fc0ea8e23dcc",
      "parents": [
        {
          "id": "9eb0dfe7dd0eaa48c5c55b6a1193f0c86f53f020"
        },
        {
          "id": "dd6fd9953b1a3568266e6a226c53093fb08a6817"
        }
      ],
      "tree": "a43281fdbc23304dcc7891321e4350e07c8cde41",
      "message": "Merge branch 'master' of github.com:sinatra/sinatra",
      "author": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "committer": {
        "name": "Konstantin Haase",
        "email": "[email protected]",
        "gravatar": "5c2b452f6eea4a6d84c105ebd971d2a4"
      },
      "authored_date": "2011-06-22T12:26:55-05:00",
      "committed_date": "2011-06-22T12:26:55-05:00"
    },
    "path": "lib/sinatra.rb",
    "blob": {
      "id": "71b122d1af6997f89ddb05ada1d1ea9821fa87fc",
      "name": "sinatra.rb",
      "mime_type": "application/ruby",
      "mode": "100644",
      "filesize": 167,
      "binary": null,
      "data": "libdir = File.dirname(__FILE__)\n$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)\n\nrequire 'sinatra/base'\nrequire 'sinatra/main'\n\nenable :inline_templates\n"
    }
  }
}

Get a RAW blob data

This request does not return JSON, it returns the actual content of the blob instead.

GET /raw?repo=sinatra&path=lib/sinatra.rb

Response:

BLOB CONTENT

Get a blob blame information

GET /blame?repo=sinatra&path=lib/sinatra.rb

Response:

{
  "result": true,
  "data": {
    "head": "master",
    "path": "lib/sinatra.rb",
    "blob": {
      "id": "71b122d1af6997f89ddb05ada1d1ea9821fa87fc",
      "name": "sinatra.rb",
      "mime_type": "application/ruby",
      "mode": "100644",
      "filesize": 167,
      "binary": null,
      "data": "libdir = File.dirname(__FILE__)\n$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)\n\nrequire 'sinatra/base'\nrequire 'sinatra/main'\n\nenable :inline_templates\n"
    },
    "blame": [
      {
        "commit": {
          "id": "0324732179f8b732abd1790dabce468b3894d756",
          "parents": [
            {
              "id": "eec7d2141685b8a44fc202a58f384bfad6c3d435"
            }
          ],
          "tree": "a5018db2cd6baf6153798885943c97850483cdb8",
          "message": "Minor tweaks to use_in_file_templates! auto loading",
          "author": {
            "name": "Ryan Tomayko",
            "email": "[email protected]",
            "gravatar": "abfc88b96ae18c85ba7aac3bded2ec5e"
          },
          "committer": {
            "name": "Ryan Tomayko",
            "email": "[email protected]",
            "gravatar": "abfc88b96ae18c85ba7aac3bded2ec5e"
          },
          "authored_date": "2009-01-16T20:45:22-06:00",
          "committed_date": "2009-01-17T19:10:10-06:00"
        },
        "lines": [
          [
            "libdir = File.dirname(__FILE__)",
            "$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)",
            ""
          ]
        ]
      },
      {
        "commit": {
          "id": "a734cf38ac0e7ddee437c8d273de50f2a4053339",
          "parents": [
            {
              "id": "d25e0208800e2fd69522e6b08e909c9c8d746b83"
            }
          ],
          "tree": "9e373aedfdc65188ee38f703c73decf8882ffec6",
          "message": "I knew I shoulda taken that left turn at Hoboken",
          "author": {
            "name": "Ryan Tomayko",
            "email": "[email protected]",
            "gravatar": "abfc88b96ae18c85ba7aac3bded2ec5e"
          },
          "committer": {
            "name": "Ryan Tomayko",
            "email": "[email protected]",
            "gravatar": "abfc88b96ae18c85ba7aac3bded2ec5e"
          },
          "authored_date": "2008-12-13T15:06:02-06:00",
          "committed_date": "2008-12-20T20:45:28-06:00"
        },
        "lines": [
          [
            "require 'sinatra/base'",
            "require 'sinatra/main'"
          ]
        ]
      },
      {
        "commit": {
          "id": "eec7d2141685b8a44fc202a58f384bfad6c3d435",
          "parents": [
            {
              "id": "15863661c33f2ba9bc03a6df325e97c285943152"
            }
          ],
          "tree": "3760c14705d0b32d632cb735e7df6d96fb4d5eb6",
          "message": "In-file-templates are automaticly loaded for you.",
          "author": {
            "name": "Blake Mizerany",
            "email": "[email protected]",
            "gravatar": "1a250566b475961b9b36abf359950c76"
          },
          "committer": {
            "name": "Blake Mizerany",
            "email": "[email protected]",
            "gravatar": "1a250566b475961b9b36abf359950c76"
          },
          "authored_date": "2009-01-16T19:01:41-06:00",
          "committed_date": "2009-01-17T19:05:17-06:00"
        },
        "lines": [
          [
            ""
          ]
        ]
      },
      {
        "commit": {
          "id": "3ef8eedef257b513f531dd48bfedcbc8df8a622b",
          "parents": [
            {
              "id": "0067232e1f75c02b9ea51bba2ca5e5fb3b7ae070"
            }
          ],
          "tree": "d65d452219fab096c381afc6872b80c73daaa30d",
          "message": "Deprecate use_in_file_templates!",
          "author": {
            "name": "Simon Rozet",
            "email": "[email protected]",
            "gravatar": "8cf17bf55c4d16cf52480619bb0b6c92"
          },
          "committer": {
            "name": "Simon Rozet",
            "email": "[email protected]",
            "gravatar": "8cf17bf55c4d16cf52480619bb0b6c92"
          },
          "authored_date": "2009-12-18T19:07:01-06:00",
          "committed_date": "2009-12-22T21:40:43-06:00"
        },
        "lines": [
          [
            "enable :inline_templates"
          ]
        ]
      }
    ]
  }
}

License

Copyright © 2011 Dan Sosedoff.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

grit-http's People

Contributors

sosedoff avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.