Changeset - 7b74079beec9
[Not reviewed]
beta
0 10 0
Mads Kiilerich - 13 years ago 2013-01-30 01:22:44
madski@unity3d.com
Transplanted from: 8625cec0e44d
coding style: fix trailing and leading spaces and tabs
10 files changed with 1838 insertions and 1848 deletions:
0 comments (0 inline, 0 general)
docs/api/api.rst
Show inline comments
 
.. _api:
 

	
 
===
 
API
 
===
 

	
 

	
 
Starting from RhodeCode version 1.2 a simple API was implemented.
 
There's a single schema for calling all api methods. API is implemented
 
with JSON protocol both ways. An url to send API request to RhodeCode is
 
<your_server>/_admin/api
 

	
 
API ACCESS FOR WEB VIEWS
 
++++++++++++++++++++++++
 

	
 
API access can also be turned on for each web view in RhodeCode that is
 
decorated with `@LoginRequired` decorator. To enable API access simple change
 
the standard login decorator to `@LoginRequired(api_access=True)`.
 
After this change, a rhodecode view can be accessed without login by adding a
 
GET parameter `?api_key=<api_key>` to url. By default this is only
 
enabled on RSS/ATOM feed views.
 

	
 

	
 
API ACCESS
 
++++++++++
 

	
 
All clients are required to send JSON-RPC spec JSON data::
 

	
 
    {
 
        "id:"<id>",
 
        "api_key":"<api_key>",
 
        "method":"<method_name>",
 
        "args":{"<arg_key>":"<arg_val>"}
 
    }
 

	
 
Example call for autopulling remotes repos using curl::
 
    curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
 

	
 
Simply provide
 
 - *id* A value of any type, which is used to match the response with the request that it is replying to.
 
 - *api_key* for access and permission validation.
 
 - *method* is name of method to call
 
 - *args* is an key:value list of arguments to pass to method
 

	
 
.. note::
 

	
 
    api_key can be found in your user account page
 

	
 

	
 
RhodeCode API will return always a JSON-RPC response::
 

	
 
    {
 
        "id":<id>, # matching id sent by request
 
        "result": "<result>"|null, # JSON formatted result, null if any errors
 
        "error": "null"|<error_message> # JSON formatted error (if any)
 
    }
 

	
 
All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
 
calling api *error* key from response will contain failure description
 
and result will be null.
 

	
 

	
 
API CLIENT
 
++++++++++
 

	
 
From version 1.4 RhodeCode adds a script that allows to easily
 
communicate with API. After installing RhodeCode a `rhodecode-api` script
 
will be available.
 

	
 
To get started quickly simply run::
 

	
 
  rhodecode-api _create_config --apikey=<youapikey> --apihost=<rhodecode host>
 

	
 
This will create a file named .config in the directory you executed it storing
 
json config file with credentials. You can skip this step and always provide
 
both of the arguments to be able to communicate with server
 

	
 

	
 
after that simply run any api command for example get_repo::
 

	
 
 rhodecode-api get_repo
 

	
 
 calling {"api_key": "<apikey>", "id": 75, "args": {}, "method": "get_repo"} to http://127.0.0.1:5000
 
 rhodecode said:
 
 {'error': 'Missing non optional `repoid` arg in JSON DATA',
 
  'id': 75,
 
  'result': None}
 

	
 
Ups looks like we forgot to add an argument
 

	
 
Let's try again now giving the repoid as parameters::
 

	
 
    rhodecode-api get_repo repoid:rhodecode
 

	
 
    calling {"api_key": "<apikey>", "id": 39, "args": {"repoid": "rhodecode"}, "method": "get_repo"} to http://127.0.0.1:5000
 
    rhodecode said:
 
    {'error': None,
 
     'id': 39,
 
     'result': <json data...>}
 

	
 

	
 

	
 
API METHODS
 
+++++++++++
 

	
 

	
 
pull
 
----
 

	
 
Pulls given repo from remote location. Can be used to automatically keep
 
remote repos up to date. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "pull"
 
    args :    {
 
                "repoid" : "<reponame or repo_id>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : "Pulled from `<reponame>`"
 
    error :  null
 

	
 

	
 
rescan_repos
 
------------
 

	
 
Dispatch rescan repositories action. If remove_obsolete is set
 
RhodeCode will delete repos that are in database but not in the filesystem.
 
This command can be executed only using api_key belonging to user with admin
 
rights.
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "rescan_repos"
 
    args :    {
 
                "remove_obsolete" : "<boolean = Optional(False)>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : "{'added': [<list of names of added repos>],
 
               'removed': [<list of names of removed repos>]}"
 
    error :  null
 

	
 

	
 
invalidate_cache
 
----------------
 

	
 
Invalidate cache for repository.
 
This command can be executed only using api_key belonging to user with admin
 
rights or regular user that have write or admin or write access to repository.
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "invalidate_cache"
 
    args :    {
 
                "repoid" : "<reponame or repo_id>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : "Cache for repository `<reponame>` was invalidated: invalidated cache keys: <list_of_cache_keys>"
 
    error :  null
 

	
 
lock
 
----
 

	
 
Set locking state on given repository by given user. If userid param is skipped
 
, then it is set to id of user whos calling this method.
 
This command can be executed only using api_key belonging to user with admin
 
rights or regular user that have admin or write access to repository.
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "lock"
 
    args :    {
 
                "repoid" : "<reponame or repo_id>"
 
                "userid" : "<user_id or username = Optional(=apiuser)>",
 
                "locked" : "<bool true|false>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : "User `<username>` set lock state for repo `<reponame>` to `true|false`"
 
    error :  null
 

	
 

	
 
show_ip
 
-------
 

	
 
Shows IP address as seen from RhodeCode server, together with all
 
defined IP addresses for given user.
 
This command can be executed only using api_key belonging to user with admin
 
rights.
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "show_ip"
 
    args :    {
 
                "userid" : "<user_id or username>",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : {
 
                 "ip_addr_server": <ip_from_clien>",
 
                 "user_ips": [
 
                                {
 
                                   "ip_addr": "<ip_with_mask>",
 
                                   "ip_range": ["<start_ip>", "<end_ip>"],
 
                                },
 
                                ...
 
                             ]
 
             }
 

	
 
    error :  null
 

	
 

	
 
get_user
 
--------
 

	
 
Get's an user by username or user_id, Returns empty result if user is not found.
 
If userid param is skipped it is set to id of user who is calling this method.
 
This command can be executed only using api_key belonging to user with admin
 
rights, or regular users that cannot specify different userid than theirs
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_user"
 
    args :    {
 
                "userid" : "<username or user_id Optional(=apiuser)>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: None if user does not exist or
 
            {
 
                "user_id" :     "<user_id>",
 
                "api_key" :     "<api_key>",
 
                "username" :    "<username>",
 
                "firstname":    "<firstname>",
 
                "lastname" :    "<lastname>",
 
                "email" :       "<email>",
 
                "emails":       "<list_of_all_additional_emails>",
 
                "ip_addresses": "<list_of_ip_addresses_for_user>",
 
                "active" :      "<bool>",
 
                "admin" :       "<bool>",
 
                "ldap_dn" :     "<ldap_dn>",
 
                "last_login":   "<last_login>",
 
                "permissions": {
 
                    "global": ["hg.create.repository",
 
                               "repository.read",
 
                               "hg.register.manual_activate"],
 
                    "repositories": {"repo1": "repository.none"},
 
                    "repositories_groups": {"Group1": "group.read"}
 
                 },
 
            }
 

	
 
    error:  null
 

	
 

	
 
get_users
 
---------
 

	
 
Lists all existing users. This command can be executed only using api_key
 
belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_users"
 
    args :    { }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: [
 
              {
 
                "user_id" :     "<user_id>",
 
                "username" :    "<username>",
 
                "firstname":    "<firstname>",
 
                "lastname" :    "<lastname>",
 
                "email" :       "<email>",
 
                "emails":       "<list_of_all_additional_emails>",
 
                "ip_addresses": "<list_of_ip_addresses_for_user>",
 
                "active" :      "<bool>",
 
                "admin" :       "<bool>",
 
                "ldap_dn" :     "<ldap_dn>",
 
                "last_login":   "<last_login>",
 
              },
 
    	      …
 
              …
 
            ]
 
    error:  null
 

	
 

	
 
create_user
 
-----------
 

	
 
Creates new user. This command can
 
be executed only using api_key belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "create_user"
 
    args :    {
 
                "username" :  "<username>",
 
                "email" :     "<useremail>",
 
                "password" :  "<password>",
 
                "firstname" : "<firstname> = Optional(None)",
 
                "lastname" :  "<lastname> = Optional(None)",
 
                "active" :    "<bool> = Optional(True)",
 
                "admin" :     "<bool> = Optional(False)",
 
                "ldap_dn" :   "<ldap_dn> = Optional(None)"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "created new user `<username>`",
 
              "user": {
 
                "user_id" :  "<user_id>",
 
                "username" : "<username>",
 
                "firstname": "<firstname>",
 
                "lastname" : "<lastname>",
 
                "email" :    "<email>",
 
                "emails":    "<list_of_all_additional_emails>",
 
                "active" :   "<bool>",
 
                "admin" :    "<bool>",
 
                "ldap_dn" :  "<ldap_dn>",
 
                "last_login": "<last_login>",
 
              },
 
            }
 
    error:  null
 

	
 

	
 
update_user
 
-----------
 

	
 
updates given user if such user exists. This command can
 
be executed only using api_key belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "update_user"
 
    args :    {
 
                "userid" : "<user_id or username>",
 
                "username" :  "<username> = Optional(None)",
 
                "email" :     "<useremail> = Optional(None)",
 
                "password" :  "<password> = Optional(None)",
 
                "firstname" : "<firstname> = Optional(None)",
 
                "lastname" :  "<lastname> = Optional(None)",
 
                "active" :    "<bool> = Optional(None)",
 
                "admin" :     "<bool> = Optional(None)",
 
                "ldap_dn" :   "<ldap_dn> = Optional(None)"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "updated user ID:<userid> <username>",
 
              "user": {
 
                "user_id" :  "<user_id>",
 
                "username" : "<username>",
 
                "firstname": "<firstname>",
 
                "lastname" : "<lastname>",
 
                "email" :    "<email>",
 
                "emails":    "<list_of_all_additional_emails>",
 
                "active" :   "<bool>",
 
                "admin" :    "<bool>",
 
                "ldap_dn" :  "<ldap_dn>",
 
                "last_login": "<last_login>",
 
              },
 
            }
 
    error:  null
 

	
 

	
 
delete_user
 
-----------
 

	
 

	
 
deletes givenuser if such user exists. This command can
 
be executed only using api_key belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "delete_user"
 
    args :    {
 
                "userid" : "<user_id or username>",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "deleted user ID:<userid> <username>",
 
              "user": null
 
            }
 
    error:  null
 

	
 

	
 
get_users_group
 
---------------
 

	
 
Gets an existing users group. This command can be executed only using api_key
 
belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_users_group"
 
    args :    {
 
                "usersgroupid" : "<users group id or name>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : None if group not exist
 
             {
 
               "users_group_id" : "<id>",
 
               "group_name" :     "<groupname>",
 
               "active":          "<bool>",
 
               "members" :  [
 
                              {
 
                                "user_id" :  "<user_id>",
 
                                "username" : "<username>",
 
                                "firstname": "<firstname>",
 
                                "lastname" : "<lastname>",
 
                                "email" :    "<email>",
 
                                "emails":    "<list_of_all_additional_emails>",
 
                                "active" :   "<bool>",
 
                                "admin" :    "<bool>",
 
                                "ldap_dn" :  "<ldap_dn>",
 
                                "last_login": "<last_login>",
 
                              },
 
                              …
 
                            ]
 
             }
 
    error : null
 

	
 

	
 
get_users_groups
 
----------------
 

	
 
Lists all existing users groups. This command can be executed only using
 
api_key belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_users_groups"
 
    args :    { }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result : [
 
               {
 
               "users_group_id" : "<id>",
 
               "group_name" :     "<groupname>",
 
               "active":          "<bool>",
 
               },
 
               …
 
              ]
 
    error : null
 

	
 

	
 
create_users_group
 
------------------
 

	
 
Creates new users group. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "create_users_group"
 
    args:     {
 
                "group_name":  "<groupname>",
 
                "active":"<bool> = Optional(True)"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg": "created new users group `<groupname>`",
 
              "users_group": {
 
                     "users_group_id" : "<id>",
 
                     "group_name" :     "<groupname>",
 
                     "active":          "<bool>",
 
               },
 
            }
 
    error:  null
 

	
 

	
 
add_user_to_users_group
 
-----------------------
 

	
 
Adds a user to a users group. If user exists in that group success will be
 
`false`. This command can be executed only using api_key
 
belonging to user with admin rights
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "add_user_users_group"
 
    args:     {
 
                "usersgroupid" : "<users group id or name>",
 
                "userid" : "<user_id or username>",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "success": True|False # depends on if member is in group
 
              "msg": "added member `<username>` to users group `<groupname>` |
 
                      User is already in that group"
 
            }
 
    error:  null
 

	
 

	
 
remove_user_from_users_group
 
----------------------------
 

	
 
Removes a user from a users group. If user is not in given group success will
 
be `false`. This command can be executed only
 
using api_key belonging to user with admin rights
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "remove_user_from_users_group"
 
    args:     {
 
                "usersgroupid" : "<users group id or name>",
 
                "userid" : "<user_id or username>",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "success":  True|False,  # depends on if member is in group
 
              "msg": "removed member <username> from users group <groupname> |
 
                      User wasn't in group"
 
            }
 
    error:  null
 

	
 

	
 
get_repo
 
--------
 

	
 
Gets an existing repository by it's name or repository_id. Members will return
 
either users_group or user associated to that repository. This command can be
 
executed only using api_key belonging to user with admin
 
rights or regular user that have at least read access to repository.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_repo"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: None if repository does not exist or
 
            {
 
                "repo_id" :          "<repo_id>",
 
                "repo_name" :        "<reponame>"
 
                "repo_type" :        "<repo_type>",
 
                "clone_uri" :        "<clone_uri>",
 
                "enable_downloads":  "<bool>",
 
                "enable_locking":    "<bool>",
 
                "enable_statistics": "<bool>",
 
                "private":           "<bool>",
 
                "created_on" :       "<date_time_created>",
 
                "description" :      "<description>",
 
                "landing_rev":       "<landing_rev>",
 
                "last_changeset":    {
 
                                       "author":   "<full_author>",
 
                                       "date":     "<date_time_of_commit>",
 
                                       "message":  "<commit_message>",
 
                                       "raw_id":   "<raw_id>",
 
                                       "revision": "<numeric_revision>",
 
                                       "short_id": "<short_id>"
 
                                     }
 
                "owner":             "<repo_owner>",
 
                "fork_of":           "<name_of_fork_parent>",
 
                "members" :     [
 
                                  {
 
                                    "type":        "user",
 
                                    "user_id" :    "<user_id>",
 
                                    "username" :   "<username>",
 
                                    "firstname":   "<firstname>",
 
                                    "lastname" :   "<lastname>",
 
                                    "email" :      "<email>",
 
                                    "emails":      "<list_of_all_additional_emails>",
 
                                    "active" :     "<bool>",
 
                                    "admin" :      "<bool>",
 
                                    "ldap_dn" :    "<ldap_dn>",
 
                                    "last_login":  "<last_login>",
 
                                    "permission" : "repository.(read|write|admin)"
 
                                  },
 
                                  …
 
                                  {
 
                                    "type":      "users_group",
 
                                    "id" :       "<usersgroupid>",
 
                                    "name" :     "<usersgroupname>",
 
                                    "active":    "<bool>",
 
                                    "permission" : "repository.(read|write|admin)"
 
                                  },
 
                                  …
 
                                ]
 
                 "followers":   [
 
                                  {
 
                                    "user_id" :     "<user_id>",
 
                                    "username" :    "<username>",
 
                                    "firstname":    "<firstname>",
 
                                    "lastname" :    "<lastname>",
 
                                    "email" :       "<email>",
 
                                    "emails":       "<list_of_all_additional_emails>",
 
                                    "ip_addresses": "<list_of_ip_addresses_for_user>",
 
                                    "active" :      "<bool>",
 
                                    "admin" :       "<bool>",
 
                                    "ldap_dn" :     "<ldap_dn>",
 
                                    "last_login":   "<last_login>",
 
                                  },
 
                                  …
 
                 ]
 
            }
 
    error:  null
 

	
 

	
 
get_repos
 
---------
 

	
 
Lists all existing repositories. This command can be executed only using
 
api_key belonging to user with admin rights or regular user that have
 
admin, write or read access to repository.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_repos"
 
    args:     { }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: [
 
              {
 
                "repo_id" :          "<repo_id>",
 
                "repo_name" :        "<reponame>"
 
                "repo_type" :        "<repo_type>",
 
                "clone_uri" :        "<clone_uri>",
 
                "private": :         "<bool>",
 
                "created_on" :       "<datetimecreated>",
 
                "description" :      "<description>",
 
                "landing_rev":       "<landing_rev>",
 
                "owner":             "<repo_owner>",
 
                "fork_of":           "<name_of_fork_parent>",
 
                "enable_downloads":  "<bool>",
 
                "enable_locking":    "<bool>",
 
                "enable_statistics": "<bool>",
 
              },
 
              …
 
            ]
 
    error:  null
 

	
 

	
 
get_repo_nodes
 
--------------
 

	
 
returns a list of nodes and it's children in a flat list for a given path
 
at given revision. It's possible to specify ret_type to show only `files` or
 
`dirs`. This command can be executed only using api_key belonging to user
 
with admin rights
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "get_repo_nodes"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
                "revision"  : "<revision>",
 
                "root_path" : "<root_path>",
 
                "ret_type"  : "<ret_type> = Optional('all')"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: [
 
              {
 
                "name" :        "<name>"
 
                "type" :        "<type>",
 
              },
 
              …
 
            ]
 
    error:  null
 

	
 

	
 
create_repo
 
-----------
 

	
 
Creates a repository. If repository name contains "/", all needed repository
 
groups will be created. For example "foo/bar/baz" will create groups
 
"foo", "bar" (with "foo" as parent), and create "baz" repository with
 
"bar" as group. This command can be executed only using api_key belonging to user with admin
 
rights or regular user that have create repository permission. Regular users
 
cannot specify owner parameter
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "create_repo"
 
    args:     {
 
                "repo_name" :        "<reponame>",
 
                "owner" :            "<onwer_name_or_id = Optional(=apiuser)>",
 
                "repo_type" :        "<repo_type> = Optional('hg')",
 
                "description" :      "<description> = Optional('')",
 
                "private" :          "<bool> = Optional(False)",
 
                "clone_uri" :        "<clone_uri> = Optional(None)",
 
                "landing_rev" :      "<landing_rev> = Optional('tip')",
 
                "enable_downloads":  "<bool> = Optional(False)",
 
                "enable_locking":    "<bool> = Optional(False)",
 
                "enable_statistics": "<bool> = Optional(False)",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg": "Created new repository `<reponame>`",
 
              "repo": {
 
                "repo_id" :          "<repo_id>",
 
                "repo_name" :        "<reponame>"
 
                "repo_type" :        "<repo_type>",
 
                "clone_uri" :        "<clone_uri>",
 
                "private": :         "<bool>",
 
                "created_on" :       "<datetimecreated>",
 
                "description" :      "<description>",
 
                "landing_rev":       "<landing_rev>",
 
                "owner":             "<username or user_id>",
 
                "fork_of":           "<name_of_fork_parent>",
 
                "enable_downloads":  "<bool>",
 
                "enable_locking":    "<bool>",
 
                "enable_statistics": "<bool>",
 
              },
 
            }
 
    error:  null
 

	
 

	
 
fork_repo
 
---------
 

	
 
Creates a fork of given repo. In case of using celery this will
 
immidiatelly return success message, while fork is going to be created
 
asynchronous. This command can be executed only using api_key belonging to
 
user with admin rights or regular user that have fork permission, and at least
 
read access to forking repository. Regular users cannot specify owner parameter.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "fork_repo"
 
    args:     {
 
                "repoid" :          "<reponame or repo_id>",
 
                "fork_name":        "<forkname>",
 
                "owner":            "<username or user_id = Optional(=apiuser)>",
 
                "description":      "<description>",
 
                "copy_permissions": "<bool>",
 
                "private":          "<bool>",
 
                "landing_rev":      "<landing_rev>"
 

	
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg": "Created fork of `<reponame>` as `<forkname>`",
 
              "success": true
 
            }
 
    error:  null
 

	
 

	
 
delete_repo
 
-----------
 

	
 
Deletes a repository. This command can be executed only using api_key belonging to user with admin
 
rights or regular user that have admin access to repository.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "delete_repo"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg": "Deleted repository `<reponame>`",
 
              "success": true
 
            }
 
    error:  null
 

	
 

	
 
grant_user_permission
 
---------------------
 

	
 
Grant permission for user on given repository, or update existing one
 
if found. This command can be executed only using api_key belonging to user
 
with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "grant_user_permission"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
                "userid" : "<username or user_id>"
 
                "perm" :       "(repository.(none|read|write|admin))",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
 
              "success": true
 
            }
 
    error:  null
 

	
 

	
 
revoke_user_permission
 
----------------------
 

	
 
Revoke permission for user on given repository. This command can be executed
 
only using api_key belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method  : "revoke_user_permission"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
                "userid" : "<username or user_id>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
 
              "success": true
 
            }
 
    error:  null
 

	
 

	
 
grant_users_group_permission
 
----------------------------
 

	
 
Grant permission for users group on given repository, or update
 
existing one if found. This command can be executed only using
 
api_key belonging to user with admin rights.
 

	
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method :  "grant_users_group_permission"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
                "usersgroupid" : "<users group id or name>"
 
                "perm" : "(repository.(none|read|write|admin))",
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
 
              "success": true
 
            }
 
    error:  null
 

	
 

	
 
revoke_users_group_permission
 
-----------------------------
 

	
 
Revoke permission for users group on given repository.This command can be
 
executed only using api_key belonging to user with admin rights.
 

	
 
INPUT::
 

	
 
    id : <id_for_response>
 
    api_key : "<api_key>"
 
    method  : "revoke_users_group_permission"
 
    args:     {
 
                "repoid" : "<reponame or repo_id>"
 
                "usersgroupid" : "<users group id or name>"
 
              }
 

	
 
OUTPUT::
 

	
 
    id : <id_given_in_input>
 
    result: {
 
              "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
 
              "success": true
 
            }
 
    error:  null
docs/installation_win.rst
Show inline comments
 
.. _installation_win:
 

	
 

	
 
Step by step Installation for Windows
 
=====================================
 

	
 

	
 
RhodeCode step-by-step install Guide for Windows
 

	
 
Target OS: Windows XP SP3 32bit English (Clean installation)
 
+ All Windows Updates until 24-may-2012
 

	
 
.. note::
 

	
 
   This installation is for 32bit systems, for 64bit windows you might need
 
   to download proper 64bit version of "Windows Installer" and Win32py
 
   extensions
 

	
 
Step1 - Install Visual Studio 2008 Express
 
------------------------------------------
 

	
 

	
 
Optional: You can also install MingW, but VS2008 installation is easier
 

	
 
Download "Visual C++ 2008 Express Edition with SP1" from:
 
http://www.microsoft.com/visualstudio/en-us/products/2008-editions/express
 
(if not found or relocated, google for "visual studio 2008 express" for
 
updated link)
 

	
 
You can also download full ISO file for offline installation, just
 
choose "All - Offline Install ISO image file" in the previous page and
 
choose "Visual C++ 2008 Express" when installing.
 

	
 
.. note::
 
    
 

	
 
  Using other versions of Visual Studio will lead to random crashes.
 
  You must use Visual Studio 2008!"
 

	
 
.. note::
 

	
 
  Silverlight Runtime and SQL Server 2008 Express Edition are not
 
  required, you can uncheck them
 

	
 

	
 
Step2 - Install Python
 
----------------------
 

	
 
Install Python 2.x.y (x >= 5) x86 version (32bit). DO NOT USE A 3.x version.
 
Download Python 2.x.y from:
 
http://www.python.org/download/
 

	
 
Choose "Windows Installer" (32bit version) not "Windows X86-64
 
Installer". While writing this guide, the latest version was v2.7.3.
 
Remember the specific major and minor version installed, because it will
 
be needed in the next step. In this case, it is "2.7".
 

	
 

	
 
Step3 - Install Win32py extensions
 
----------------------------------
 

	
 
Download pywin32 from:
 
http://sourceforge.net/projects/pywin32/files/
 

	
 
- Click on "pywin32" folder
 
- Click on the first folder (in this case, Build 217, maybe newer when you try)
 
- Choose the file ending with ".win32-py2.x.exe" -> x being the minor
 
  version of Python you installed (in this case, 7)
 
  When writing this guide, the file was:
 
  http://sourceforge.net/projects/pywin32/files/pywin32/Build%20217/pywin32-217.win32-py2.7.exe/download
 

	
 

	
 
Step4 - Python BIN
 
------------------
 

	
 
Add Python BIN folder to the path
 

	
 
You have to add the Python folder to the path, you can do it manually
 
(editing "PATH" environment variable) or using Windows Support Tools
 
that came preinstalled in Vista/7 and can be installed in Windows XP.
 

	
 
- Using support tools on WINDOWS XP:
 
  If you use Windows XP you can install them using Windows XP CD and
 
  navigating to \SUPPORT\TOOLS. There, execute Setup.EXE (not MSI).
 
  Afterwards, open a CMD and type::
 

	
 
    SETX PATH "%PATH%;[your-python-path]" -M
 

	
 
  Close CMD (the path variable will be updated then)
 

	
 
- Using support tools on WINDOWS Vista/7:
 

	
 
  Open a CMD and type::
 

	
 
    SETX PATH "%PATH%;[your-python-path]" /M
 

	
 
  Please substitute [your-python-path] with your Python installation path.
 
  Typically: C:\\Python27
 

	
 

	
 
Step5 - RhodeCode folder structure
 
----------------------------------
 

	
 
Create a RhodeCode folder structure
 

	
 
This is only a example to install RhodeCode, you can of course change
 
it. However, this guide will follow the proposed structure, so please
 
later adapt the paths if you change them. My recommendation is to use
 
folders with NO SPACES. But you can try if you are brave...
 

	
 
Create the following folder structure::
 

	
 
  C:\RhodeCode
 
  C:\RhodeCode\Bin
 
  C:\RhodeCode\Env
 
  C:\RhodeCode\Repos
 

	
 

	
 
Step6 - Install virtualenv
 
---------------------------
 

	
 
Install Virtual Env for Python
 

	
 
Navigate to: http://www.virtualenv.org/en/latest/index.html#installation
 
Right click on "virtualenv.py" file and choose "Save link as...".
 
Download to C:\\RhodeCode (or whatever you want)
 
(the file is located at
 
https://raw.github.com/pypa/virtualenv/master/virtualenv.py)
 

	
 
Create a virtual Python environment in C:\\RhodeCode\\Env (or similar). To
 
do so, open a CMD (Python Path should be included in Step3), navigate
 
where you downloaded "virtualenv.py", and write::
 

	
 
 python virtualenv.py C:\RhodeCode\Env
 

	
 
(--no-site-packages is now the default behaviour of virtualenv, no need
 
to include it)
 

	
 

	
 
Step7 - Install RhodeCode
 
-------------------------
 

	
 
Finally, install RhodeCode
 

	
 
Close previously opened command prompt/s, and open a Visual Studio 2008
 
Command Prompt (**IMPORTANT!!**). To do so, go to Start Menu, and then open
 
"Microsoft Visual C++ 2008 Express Edition" -> "Visual Studio Tools" ->
 
"Visual Studio 2008 Command Prompt"
 

	
 
In that CMD (loaded with VS2008 PATHs) type::
 

	
 
  cd C:\RhodeCode\Env\Scripts (or similar)
 
  activate
 

	
 
The prompt will change into "(Env) C:\\RhodeCode\\Env\\Scripts" or similar
 
(depending of your folder structure). Then type::
 

	
 
 pip install rhodecode
 

	
 
(long step, please wait until fully complete)
 

	
 
Some warnings will appear, don't worry as they are normal.
 

	
 

	
 
Step8 - Configuring RhodeCode
 
-----------------------------
 

	
 

	
 
steps taken from http://packages.python.org/RhodeCode/setup.html
 

	
 
You have to use the same Visual Studio 2008 command prompt as Step7, so
 
if you closed it reopen it following the same commands (including the
 
"activate" one). When ready, just type::
 

	
 
  cd C:\RhodeCode\Bin
 
  paster make-config RhodeCode production.ini
 

	
 
Then, you must edit production.ini to fit your needs (ip address, ip
 
port, mail settings, database, whatever). I recommend using NotePad++
 
(free) or similar text editor, as it handles well the EndOfLine
 
character differences between Unix and Windows
 
(http://notepad-plus-plus.org/)
 

	
 
For the sake of simplicity lets run it with the default settings. After
 
your edits (if any), in the previous Command Prompt, type::
 

	
 
 paster setup-rhodecode production.ini
 

	
 
(this time a NEW database will be installed, you must follow a different
 
step to later UPGRADE to a newer RhodeCode version)
 

	
 
The script will ask you for confirmation about creating a NEW database,
 
answer yes (y)
 
The script will ask you for repository path, answer C:\\RhodeCode\\Repos
 
(or similar)
 
The script will ask you for admin username and password, answer "admin"
 
+ "123456" (or whatever you want)
 
The script will ask you for admin mail, answer "admin@xxxx.com" (or
 
whatever you want)
 

	
 
If you make some mistake and the script does not end, don't worry, start
 
it again.
 

	
 

	
 
Step9 - Running RhodeCode
 
-------------------------
 

	
 

	
 
In the previous command prompt, being in the C:\\RhodeCode\\Bin folder,
 
just type::
 

	
 
 paster serve production.ini
 

	
 
Open yout web server, and go to http://127.0.0.1:5000
 

	
 
It works!! :-)
 

	
 
Remark:
 
If it does not work first time, just Ctrl-C the CMD process and start it
 
again. Don't forget the "http://" in Internet Explorer
 

	
 

	
 

	
 
What this Guide does not cover:
 

	
 
- Installing Celery
 
- Running RhodeCode as Windows Service. You can investigate here:
 

	
 
  - http://pypi.python.org/pypi/wsgisvc
 
  - http://ryrobes.com/python/running-python-scripts-as-a-windows-service/
 
  - http://wiki.pylonshq.com/display/pylonscookbook/How+to+run+Pylons+as+a+Windows+service
 

	
 
- Using Apache. You can investigate here:
 

	
 
  - https://groups.google.com/group/rhodecode/msg/c433074e813ffdc4
 

	
 

	
 
Upgrading
 
=========
 

	
 
Stop running RhodeCode
 
Open a CommandPrompt like in Step7 (VS2008 path + activate) and type::
 

	
 
 easy_install -U rhodecode
 
 cd \RhodeCode\Bin
 

	
 
{ backup your production.ini file now} ::
 

	
 
 paster make-config RhodeCode production.ini
 

	
 
(check changes and update your production.ini accordingly) ::
 

	
 
 paster upgrade-db production.ini (update database)
 

	
 
Full steps in http://packages.python.org/RhodeCode/upgrade.html
docs/setup.rst
Show inline comments
 
.. _setup:
 

	
 
=====
 
Setup
 
=====
 

	
 

	
 
Setting up RhodeCode
 
--------------------
 

	
 
First, you will need to create a RhodeCode configuration file. Run the
 
following command to do this::
 

	
 
    paster make-config RhodeCode production.ini
 

	
 
- This will create the file `production.ini` in the current directory. This
 
  configuration file contains the various settings for RhodeCode, e.g proxy
 
  port, email settings, usage of static files, cache, celery settings and
 
  logging.
 

	
 

	
 
Next, you need to create the databases used by RhodeCode. I recommend that you
 
use postgresql or sqlite (default). If you choose a database other than the
 
default ensure you properly adjust the db url in your production.ini
 
configuration file to use this other database. RhodeCode currently supports
 
postgresql, sqlite and mysql databases. Create the database by running
 
the following command::
 

	
 
    paster setup-rhodecode production.ini
 

	
 
This will prompt you for a "root" path. This "root" path is the location where
 
RhodeCode will store all of its repositories on the current machine. After
 
entering this "root" path ``setup-rhodecode`` will also prompt you for a username
 
and password for the initial admin account which ``setup-rhodecode`` sets
 
up for you.
 

	
 
setup process can be fully automated, example for lazy::
 

	
 
    paster setup-rhodecode production.ini --user=marcink --password=secret --email=marcin@rhodecode.org --repos=/home/marcink/my_repos
 

	
 

	
 
- The ``setup-rhodecode`` command will create all of the needed tables and an
 
  admin account. When choosing a root path you can either use a new empty
 
  location, or a location which already contains existing repositories. If you
 
  choose a location which contains existing repositories RhodeCode will simply
 
  add all of the repositories at the chosen location to it's database.
 
  (Note: make sure you specify the correct path to the root).
 
- Note: the given path for mercurial_ repositories **must** be write accessible
 
  for the application. It's very important since the RhodeCode web interface
 
  will work without write access, but when trying to do a push it will
 
  eventually fail with permission denied errors unless it has write access.
 

	
 
You are now ready to use RhodeCode, to run it simply execute::
 

	
 
    paster serve production.ini
 

	
 
- This command runs the RhodeCode server. The web app should be available at the
 
  127.0.0.1:5000. This ip and port is configurable via the production.ini
 
  file created in previous step
 
- Use the admin account you created above when running ``setup-rhodecode``
 
  to login to the web app.
 
- The default permissions on each repository is read, and the owner is admin.
 
  Remember to update these if needed.
 
- In the admin panel you can toggle ldap, anonymous, permissions settings. As
 
  well as edit more advanced options on users and repositories
 

	
 
Optionally users can create `rcextensions` package that extends RhodeCode
 
functionality. To do this simply execute::
 

	
 
    paster make-rcext production.ini
 

	
 
This will create `rcextensions` package in the same place that your `ini` file
 
lives. With `rcextensions` it's possible to add additional mapping for whoosh,
 
stats and add additional code into the push/pull/create/delete repo hooks.
 
For example for sending signals to build-bots such as jenkins.
 
Please see the `__init__.py` file inside `rcextensions` package
 
for more details.
 

	
 

	
 
Using RhodeCode with SSH
 
------------------------
 

	
 
RhodeCode currently only hosts repositories using http and https. (The addition
 
of ssh hosting is a planned future feature.) However you can easily use ssh in
 
parallel with RhodeCode. (Repository access via ssh is a standard "out of
 
the box" feature of mercurial_ and you can use this to access any of the
 
repositories that RhodeCode is hosting. See PublishingRepositories_)
 

	
 
RhodeCode repository structures are kept in directories with the same name
 
as the project. When using repository groups, each group is a subdirectory.
 
This allows you to easily use ssh for accessing repositories.
 

	
 
In order to use ssh you need to make sure that your web-server and the users
 
login accounts have the correct permissions set on the appropriate directories.
 
(Note that these permissions are independent of any permissions you have set up
 
using the RhodeCode web interface.)
 

	
 
If your main directory (the same as set in RhodeCode settings) is for example
 
set to **/home/hg** and the repository you are using is named `rhodecode`, then
 
to clone via ssh you should run::
 

	
 
    hg clone ssh://user@server.com/home/hg/rhodecode
 

	
 
Using other external tools such as mercurial-server_ or using ssh key based
 
authentication is fully supported.
 

	
 
Note: In an advanced setup, in order for your ssh access to use the same
 
permissions as set up via the RhodeCode web interface, you can create an
 
authentication hook to connect to the rhodecode db and runs check functions for
 
permissions against that.
 

	
 
Setting up Whoosh full text search
 
----------------------------------
 

	
 
Starting from version 1.1 the whoosh index can be build by using the paster
 
command ``make-index``. To use ``make-index`` you must specify the configuration
 
file that stores the location of the index. You may specify the location of the
 
repositories (`--repo-location`).  If not specified, this value is retrieved
 
from the RhodeCode database.  This was required prior to 1.2.  Starting from
 
version 1.2 it is also possible to specify a comma separated list of
 
repositories (`--index-only`) to build index only on chooses repositories
 
skipping any other found in repos location
 

	
 
You may optionally pass the option `-f` to enable a full index rebuild. Without
 
the `-f` option, indexing will run always in "incremental" mode.
 

	
 
For an incremental index build use::
 

	
 
	paster make-index production.ini
 
    paster make-index production.ini
 

	
 
For a full index rebuild use::
 

	
 
	paster make-index production.ini -f
 
    paster make-index production.ini -f
 

	
 

	
 
building index just for chosen repositories is possible with such command::
 

	
 
 paster make-index production.ini --index-only=vcs,rhodecode
 

	
 

	
 
In order to do periodical index builds and keep your index always up to date.
 
It's recommended to do a crontab entry for incremental indexing.
 
An example entry might look like this::
 

	
 
    /path/to/python/bin/paster make-index /path/to/rhodecode/production.ini
 

	
 
When using incremental mode (the default) whoosh will check the last
 
modification date of each file and add it to be reindexed if a newer file is
 
available. The indexing daemon checks for any removed files and removes them
 
from index.
 

	
 
If you want to rebuild index from scratch, you can use the `-f` flag as above,
 
or in the admin panel you can check `build from scratch` flag.
 

	
 

	
 
Setting up LDAP support
 
-----------------------
 

	
 
RhodeCode starting from version 1.1 supports ldap authentication. In order
 
to use LDAP, you have to install the python-ldap_ package. This package is
 
available via pypi, so you can install it by running
 

	
 
using easy_install::
 

	
 
    easy_install python-ldap
 

	
 
using pip::
 

	
 
    pip install python-ldap
 

	
 
.. note::
 
   python-ldap requires some certain libs on your system, so before installing
 
   it check that you have at least `openldap`, and `sasl` libraries.
 

	
 
LDAP settings are located in admin->ldap section,
 

	
 
Here's a typical ldap setup::
 

	
 
 Connection settings
 
 Enable LDAP          = checked
 
 Host                 = host.example.org
 
 Port                 = 389
 
 Account              = <account>
 
 Password             = <password>
 
 Connection Security  = LDAPS connection
 
 Certificate Checks   = DEMAND
 

	
 
 Search settings
 
 Base DN              = CN=users,DC=host,DC=example,DC=org
 
 LDAP Filter          = (&(objectClass=user)(!(objectClass=computer)))
 
 LDAP Search Scope    = SUBTREE
 

	
 
 Attribute mappings
 
 Login Attribute      = uid
 
 First Name Attribute = firstName
 
 Last Name Attribute  = lastName
 
 E-mail Attribute     = mail
 

	
 
.. _enable_ldap:
 

	
 
Enable LDAP : required
 
    Whether to use LDAP for authenticating users.
 

	
 
.. _ldap_host:
 

	
 
Host : required
 
    LDAP server hostname or IP address. Can be also a comma separated
 
    list of servers to support LDAP fail-over.
 

	
 
.. _Port:
 

	
 
Port : required
 
    389 for un-encrypted LDAP, 636 for SSL-encrypted LDAP.
 

	
 
.. _ldap_account:
 

	
 
Account : optional
 
    Only required if the LDAP server does not allow anonymous browsing of
 
    records.  This should be a special account for record browsing.  This
 
    will require `LDAP Password`_ below.
 

	
 
.. _LDAP Password:
 

	
 
Password : optional
 
    Only required if the LDAP server does not allow anonymous browsing of
 
    records.
 

	
 
.. _Enable LDAPS:
 

	
 
Connection Security : required
 
    Defines the connection to LDAP server
 

	
 
    No encryption
 
        Plain non encrypted connection
 

	
 
    LDAPS connection
 
        Enable ldaps connection. It will likely require `Port`_ to be set to
 
        a different value (standard LDAPS port is 636). When LDAPS is enabled
 
        then `Certificate Checks`_ is required.
 

	
 
    START_TLS on LDAP connection
 
        START TLS connection
 

	
 
.. _Certificate Checks:
 

	
 
Certificate Checks : optional
 
    How SSL certificates verification is handled - this is only useful when
 
    `Enable LDAPS`_ is enabled.  Only DEMAND or HARD offer full SSL security
 
    while the other options are susceptible to man-in-the-middle attacks.  SSL
 
    certificates can be installed to /etc/openldap/cacerts so that the
 
    DEMAND or HARD options can be used with self-signed certificates or
 
    certificates that do not have traceable certificates of authority.
 

	
 
    NEVER
 
        A serve certificate will never be requested or checked.
 

	
 
    ALLOW
 
        A server certificate is requested.  Failure to provide a
 
        certificate or providing a bad certificate will not terminate the
 
        session.
 

	
 
    TRY
 
        A server certificate is requested.  Failure to provide a
 
        certificate does not halt the session; providing a bad certificate
 
        halts the session.
 

	
 
    DEMAND
 
        A server certificate is requested and must be provided and
 
        authenticated for the session to proceed.
 

	
 
    HARD
 
        The same as DEMAND.
 

	
 
.. _Base DN:
 

	
 
Base DN : required
 
    The Distinguished Name (DN) where searches for users will be performed.
 
    Searches can be controlled by `LDAP Filter`_ and `LDAP Search Scope`_.
 

	
 
.. _LDAP Filter:
 

	
 
LDAP Filter : optional
 
    A LDAP filter defined by RFC 2254.  This is more useful when `LDAP
 
    Search Scope`_ is set to SUBTREE.  The filter is useful for limiting
 
    which LDAP objects are identified as representing Users for
 
    authentication.  The filter is augmented by `Login Attribute`_ below.
 
    This can commonly be left blank.
 

	
 
.. _LDAP Search Scope:
 

	
 
LDAP Search Scope : required
 
    This limits how far LDAP will search for a matching object.
 

	
 
    BASE
 
        Only allows searching of `Base DN`_ and is usually not what you
 
        want.
 

	
 
    ONELEVEL
 
        Searches all entries under `Base DN`_, but not Base DN itself.
 

	
 
    SUBTREE
 
        Searches all entries below `Base DN`_, but not Base DN itself.
 
        When using SUBTREE `LDAP Filter`_ is useful to limit object
 
        location.
 

	
 
.. _Login Attribute:
 

	
 
Login Attribute : required
 
    The LDAP record attribute that will be matched as the USERNAME or
 
    ACCOUNT used to connect to RhodeCode.  This will be added to `LDAP
 
    Filter`_ for locating the User object.  If `LDAP Filter`_ is specified as
 
    "LDAPFILTER", `Login Attribute`_ is specified as "uid" and the user has
 
    connected as "jsmith" then the `LDAP Filter`_ will be augmented as below
 
    ::
 

	
 
        (&(LDAPFILTER)(uid=jsmith))
 

	
 
.. _ldap_attr_firstname:
 

	
 
First Name Attribute : required
 
    The LDAP record attribute which represents the user's first name.
 

	
 
.. _ldap_attr_lastname:
 

	
 
Last Name Attribute : required
 
    The LDAP record attribute which represents the user's last name.
 

	
 
.. _ldap_attr_email:
 

	
 
Email Attribute : required
 
    The LDAP record attribute which represents the user's email address.
 

	
 
If all data are entered correctly, and python-ldap_ is properly installed
 
users should be granted access to RhodeCode with ldap accounts.  At this
 
time user information is copied from LDAP into the RhodeCode user database.
 
This means that updates of an LDAP user object may not be reflected as a
 
user update in RhodeCode.
 

	
 
If You have problems with LDAP access and believe You entered correct
 
information check out the RhodeCode logs, any error messages sent from LDAP
 
will be saved there.
 

	
 
Active Directory
 
''''''''''''''''
 

	
 
RhodeCode can use Microsoft Active Directory for user authentication.  This
 
is done through an LDAP or LDAPS connection to Active Directory.  The
 
following LDAP configuration settings are typical for using Active
 
Directory ::
 

	
 
 Base DN              = OU=SBSUsers,OU=Users,OU=MyBusiness,DC=v3sys,DC=local
 
 Login Attribute      = sAMAccountName
 
 First Name Attribute = givenName
 
 Last Name Attribute  = sn
 
 E-mail Attribute     = mail
 

	
 
All other LDAP settings will likely be site-specific and should be
 
appropriately configured.
 

	
 

	
 
Authentication by container or reverse-proxy
 
--------------------------------------------
 

	
 
Starting with version 1.3, RhodeCode supports delegating the authentication
 
of users to its WSGI container, or to a reverse-proxy server through which all
 
clients access the application.
 

	
 
When these authentication methods are enabled in RhodeCode, it uses the
 
username that the container/proxy (Apache/Nginx/etc) authenticated and doesn't
 
perform the authentication itself. The authorization, however, is still done by
 
RhodeCode according to its settings.
 

	
 
When a user logs in for the first time using these authentication methods,
 
a matching user account is created in RhodeCode with default permissions. An
 
administrator can then modify it using RhodeCode's admin interface.
 
It's also possible for an administrator to create accounts and configure their
 
permissions before the user logs in for the first time.
 

	
 
Container-based authentication
 
''''''''''''''''''''''''''''''
 

	
 
In a container-based authentication setup, RhodeCode reads the user name from
 
the ``REMOTE_USER`` server variable provided by the WSGI container.
 

	
 
After setting up your container (see `Apache's WSGI config`_), you'd need
 
to configure it to require authentication on the location configured for
 
RhodeCode.
 

	
 
In order for RhodeCode to start using the provided username, you should set the
 
following in the [app:main] section of your .ini file::
 

	
 
    container_auth_enabled = true
 

	
 

	
 
Proxy pass-through authentication
 
'''''''''''''''''''''''''''''''''
 

	
 
In a proxy pass-through authentication setup, RhodeCode reads the user name
 
from the ``X-Forwarded-User`` request header, which should be configured to be
 
sent by the reverse-proxy server.
 

	
 
After setting up your proxy solution (see `Apache virtual host reverse proxy example`_,
 
`Apache as subdirectory`_ or `Nginx virtual host example`_), you'd need to
 
configure the authentication and add the username in a request header named
 
``X-Forwarded-User``.
 

	
 
For example, the following config section for Apache sets a subdirectory in a
 
reverse-proxy setup with basic auth::
 

	
 
    <Location /<someprefix> >
 
      ProxyPass http://127.0.0.1:5000/<someprefix>
 
      ProxyPassReverse http://127.0.0.1:5000/<someprefix>
 
      SetEnvIf X-Url-Scheme https HTTPS=1
 

	
 
      AuthType Basic
 
      AuthName "RhodeCode authentication"
 
      AuthUserFile /home/web/rhodecode/.htpasswd
 
      require valid-user
 

	
 
      RequestHeader unset X-Forwarded-User
 

	
 
      RewriteEngine On
 
      RewriteCond %{LA-U:REMOTE_USER} (.+)
 
      RewriteRule .* - [E=RU:%1]
 
      RequestHeader set X-Forwarded-User %{RU}e
 
    </Location>
 

	
 
In order for RhodeCode to start using the forwarded username, you should set
 
the following in the [app:main] section of your .ini file::
 

	
 
    proxypass_auth_enabled = true
 

	
 
.. note::
 
   If you enable proxy pass-through authentication, make sure your server is
 
   only accessible through the proxy. Otherwise, any client would be able to
 
   forge the authentication header and could effectively become authenticated
 
   using any account of their liking.
 

	
 
Integration with Issue trackers
 
-------------------------------
 

	
 
RhodeCode provides a simple integration with issue trackers. It's possible
 
to define a regular expression that will fetch issue id stored in commit
 
messages and replace that with an url to this issue. To enable this simply
 
uncomment following variables in the ini file::
 

	
 
    url_pat = (?:^#|\s#)(\w+)
 
    issue_server_link = https://myissueserver.com/{repo}/issue/{id}
 
    issue_prefix = #
 

	
 
`url_pat` is the regular expression that will fetch issues from commit messages.
 
Default regex will match issues in format of #<number> eg. #300.
 

	
 
Matched issues will be replace with the link specified as `issue_server_link`
 
{id} will be replaced with issue id, and {repo} with repository name.
 
Since the # is striped `issue_prefix` is added as a prefix to url.
 
`issue_prefix` can be something different than # if you pass
 
ISSUE- as issue prefix this will generate an url in format::
 

	
 
  <a href="https://myissueserver.com/example_repo/issue/300">ISSUE-300</a>
 

	
 
Hook management
 
---------------
 

	
 
Hooks can be managed in similar way to this used in .hgrc files.
 
To access hooks setting click `advanced setup` on Hooks section of Mercurial
 
Settings in Admin.
 

	
 
There are 4 built in hooks that cannot be changed (only enable/disable by
 
checkboxes on previos section).
 
To add another custom hook simply fill in first section with
 
<name>.<hook_type> and the second one with hook path. Example hooks
 
can be found at *rhodecode.lib.hooks*.
 

	
 

	
 
Changing default encoding
 
-------------------------
 

	
 
By default RhodeCode uses utf8 encoding, starting from 1.3 series this
 
can be changed, simply edit default_encoding in .ini file to desired one.
 
This affects many parts in rhodecode including commiters names, filenames,
 
encoding of commit messages. In addition RhodeCode can detect if `chardet`
 
library is installed. If `chardet` is detected RhodeCode will fallback to it
 
when there are encode/decode errors.
 

	
 

	
 
Setting Up Celery
 
-----------------
 

	
 
Since version 1.1 celery is configured by the rhodecode ini configuration files.
 
Simply set use_celery=true in the ini file then add / change the configuration
 
variables inside the ini file.
 

	
 
Remember that the ini files use the format with '.' not with '_' like celery.
 
So for example setting `BROKER_HOST` in celery means setting `broker.host` in
 
the config file.
 

	
 
In order to start using celery run::
 

	
 
 paster celeryd <configfile.ini>
 

	
 

	
 
.. note::
 
   Make sure you run this command from the same virtualenv, and with the same
 
   user that rhodecode runs.
 

	
 
HTTPS support
 
-------------
 

	
 
There are two ways to enable https:
 

	
 
- Set HTTP_X_URL_SCHEME in your http server headers, than rhodecode will
 
  recognize this headers and make proper https redirections
 
- Alternatively, change the `force_https = true` flag in the ini configuration
 
  to force using https, no headers are needed than to enable https
 

	
 

	
 
Nginx virtual host example
 
--------------------------
 

	
 
Sample config for nginx using proxy::
 

	
 
    upstream rc {
 
        server 127.0.0.1:5000;
 
        # add more instances for load balancing
 
        #server 127.0.0.1:5001;
 
        #server 127.0.0.1:5002;
 
    }
 

	
 
    server {
 
       listen          443;
 
       server_name     rhodecode.myserver.com;
 
       access_log      /var/log/nginx/rhodecode.access.log;
 
       error_log       /var/log/nginx/rhodecode.error.log;
 

	
 
       ssl on;
 
       ssl_certificate     rhodecode.myserver.com.crt;
 
       ssl_certificate_key rhodecode.myserver.com.key;
 

	
 
       ssl_session_timeout 5m;
 

	
 
       ssl_protocols SSLv3 TLSv1;
 
       ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
 
       ssl_prefer_server_ciphers on;
 

	
 
       # uncomment if you have nginx with chunking module compiled
 
       # fixes the issues of having to put postBuffer data for large git
 
       # pushes
 
       #chunkin on;
 
       #error_page 411 = @my_411_error;
 
       #location @my_411_error {
 
       #    chunkin_resume;
 
       #}
 

	
 
       # uncomment if you want to serve static files by nginx
 
       #root /path/to/installation/rhodecode/public;
 

	
 
       location / {
 
            try_files $uri @rhode;
 
       }
 

	
 
       location @rhode {
 
            proxy_pass      http://rc;
 
            include         /etc/nginx/proxy.conf;
 
       }
 

	
 
    }
 

	
 
Here's the proxy.conf. It's tuned so it will not timeout on long
 
pushes or large pushes::
 

	
 
    proxy_redirect              off;
 
    proxy_set_header            Host $host;
 
    proxy_set_header            X-Url-Scheme $scheme;
 
    proxy_set_header            X-Host $http_host;
 
    proxy_set_header            X-Real-IP $remote_addr;
 
    proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
 
    proxy_set_header            Proxy-host $proxy_host;
 
    client_max_body_size        400m;
 
    client_body_buffer_size     128k;
 
    proxy_buffering             off;
 
    proxy_connect_timeout       7200;
 
    proxy_send_timeout          7200;
 
    proxy_read_timeout          7200;
 
    proxy_buffers               8 32k;
 

	
 
Also, when using root path with nginx you might set the static files to false
 
in the production.ini file::
 

	
 
    [app:main]
 
      use = egg:rhodecode
 
      full_stack = true
 
      static_files = false
 
      lang=en
 
      cache_dir = %(here)s/data
 

	
 
In order to not have the statics served by the application. This improves speed.
 

	
 

	
 
Apache virtual host reverse proxy example
 
-----------------------------------------
 

	
 
Here is a sample configuration file for apache using proxy::
 

	
 
    <VirtualHost *:80>
 
            ServerName hg.myserver.com
 
            ServerAlias hg.myserver.com
 

	
 
            <Proxy *>
 
              Order allow,deny
 
              Allow from all
 
            </Proxy>
 

	
 
            #important !
 
            #Directive to properly generate url (clone url) for pylons
 
            ProxyPreserveHost On
 

	
 
            #rhodecode instance
 
            ProxyPass / http://127.0.0.1:5000/
 
            ProxyPassReverse / http://127.0.0.1:5000/
 

	
 
            #to enable https use line below
 
            #SetEnvIf X-Url-Scheme https HTTPS=1
 

	
 
    </VirtualHost>
 

	
 

	
 
Additional tutorial
 
http://wiki.pylonshq.com/display/pylonscookbook/Apache+as+a+reverse+proxy+for+Pylons
 

	
 

	
 
Apache as subdirectory
 
----------------------
 

	
 
Apache subdirectory part::
 

	
 
    <Location /<someprefix> >
 
      ProxyPass http://127.0.0.1:5000/<someprefix>
 
      ProxyPassReverse http://127.0.0.1:5000/<someprefix>
 
      SetEnvIf X-Url-Scheme https HTTPS=1
 
    </Location>
 

	
 
Besides the regular apache setup you will need to add the following line
 
into [app:main] section of your .ini file::
 

	
 
    filter-with = proxy-prefix
 

	
 
Add the following at the end of the .ini file::
 

	
 
    [filter:proxy-prefix]
 
    use = egg:PasteDeploy#prefix
 
    prefix = /<someprefix>
 

	
 

	
 
then change <someprefix> into your choosen prefix
 

	
 
Apache's WSGI config
 
--------------------
 

	
 
Alternatively, RhodeCode can be set up with Apache under mod_wsgi. For
 
that, you'll need to:
 

	
 
- Install mod_wsgi. If using a Debian-based distro, you can install
 
  the package libapache2-mod-wsgi::
 

	
 
    aptitude install libapache2-mod-wsgi
 

	
 
- Enable mod_wsgi::
 

	
 
    a2enmod wsgi
 

	
 
- Create a wsgi dispatch script, like the one below. Make sure you
 
  check the paths correctly point to where you installed RhodeCode
 
  and its Python Virtual Environment.
 
- Enable the WSGIScriptAlias directive for the wsgi dispatch script,
 
  as in the following example. Once again, check the paths are
 
  correctly specified.
 

	
 
Here is a sample excerpt from an Apache Virtual Host configuration file::
 

	
 
    WSGIDaemonProcess pylons \
 
        threads=4 \
 
        python-path=/home/web/rhodecode/pyenv/lib/python2.6/site-packages
 
    WSGIScriptAlias / /home/web/rhodecode/dispatch.wsgi
 
    WSGIPassAuthorization On
 

	
 
.. note::
 
   when running apache as root please add: `user=www-data group=www-data`
 
   into above configuration
 

	
 
.. note::
 
   RhodeCode cannot be runned in multiprocess mode in apache, make sure
 
   you don't specify `processes=num` directive in the config
 

	
 

	
 
Example wsgi dispatch script::
 

	
 
    import os
 
    os.environ["HGENCODING"] = "UTF-8"
 
    os.environ['PYTHON_EGG_CACHE'] = '/home/web/rhodecode/.egg-cache'
 

	
 
    # sometimes it's needed to set the curent dir
 
    os.chdir('/home/web/rhodecode/')
 

	
 
    import site
 
    site.addsitedir("/home/web/rhodecode/pyenv/lib/python2.6/site-packages")
 

	
 
    from paste.deploy import loadapp
 
    from paste.script.util.logging_config import fileConfig
 

	
 
    fileConfig('/home/web/rhodecode/production.ini')
 
    application = loadapp('config:/home/web/rhodecode/production.ini')
 

	
 
Note: when using mod_wsgi you'll need to install the same version of
 
Mercurial that's inside RhodeCode's virtualenv also on the system's Python
 
environment.
 

	
 

	
 
Other configuration files
 
-------------------------
 

	
 
Some example init.d scripts can be found in init.d directory::
 

	
 
  https://secure.rhodecode.org/rhodecode/files/beta/init.d
 

	
 
.. _virtualenv: http://pypi.python.org/pypi/virtualenv
 
.. _python: http://www.python.org/
 
.. _mercurial: http://mercurial.selenic.com/
 
.. _celery: http://celeryproject.org/
 
.. _rabbitmq: http://www.rabbitmq.com/
 
.. _python-ldap: http://www.python-ldap.org/
 
.. _mercurial-server: http://www.lshift.net/mercurial-server.html
 
.. _PublishingRepositories: http://mercurial.selenic.com/wiki/PublishingRepositories
 
.. _Issues tracker: https://bitbucket.org/marcinkuzminski/rhodecode/issues
 
.. _google group rhodecode: http://groups.google.com/group/rhodecode
rhodecode/controllers/files.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.controllers.files
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    Files controller for RhodeCode
 

	
 
    :created_on: Apr 21, 2010
 
    :author: marcink
 
    :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
from __future__ import with_statement
 
import os
 
import logging
 
import traceback
 
import tempfile
 

	
 
from pylons import request, response, tmpl_context as c, url
 
from pylons.i18n.translation import _
 
from pylons.controllers.util import redirect
 
from rhodecode.lib.utils import jsonify
 

	
 
from rhodecode.lib import diffs
 
from rhodecode.lib import helpers as h
 

	
 
from rhodecode.lib.compat import OrderedDict
 
from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str,\
 
    str2bool
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
from rhodecode.lib.vcs.conf import settings
 
from rhodecode.lib.vcs.exceptions import RepositoryError, \
 
    ChangesetDoesNotExistError, EmptyRepositoryError, \
 
    ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError,\
 
    NodeDoesNotExistError, ChangesetError, NodeError
 
from rhodecode.lib.vcs.nodes import FileNode
 

	
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.db import Repository
 

	
 
from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
 
    _context_url, get_line_ctx, get_ignore_ws
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class FilesController(BaseRepoController):
 

	
 
    def __before__(self):
 
        super(FilesController, self).__before__()
 
        c.cut_off_limit = self.cut_off_limit
 

	
 
    def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True):
 
        """
 
        Safe way to get changeset if error occur it redirects to tip with
 
        proper message
 

	
 
        :param rev: revision to fetch
 
        :param repo_name: repo name to redirect after
 
        """
 

	
 
        try:
 
            return c.rhodecode_repo.get_changeset(rev)
 
        except EmptyRepositoryError, e:
 
            if not redirect_after:
 
                return None
 
            url_ = url('files_add_home',
 
                       repo_name=c.repo_name,
 
                       revision=0, f_path='')
 
            add_new = '<a href="%s">[%s]</a>' % (url_, _('click here to add new file'))
 
            h.flash(h.literal(_('There are no files yet %s') % add_new),
 
                    category='warning')
 
            redirect(h.url('summary_home', repo_name=repo_name))
 

	
 
        except RepositoryError, e:
 
            h.flash(str(e), category='warning')
 
            redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
 

	
 
    def __get_filenode_or_redirect(self, repo_name, cs, path):
 
        """
 
        Returns file_node, if error occurs or given path is directory,
 
        it'll redirect to top level path
 

	
 
        :param repo_name: repo_name
 
        :param cs: given changeset
 
        :param path: path to lookup
 
        """
 

	
 
        try:
 
            file_node = cs.get_node(path)
 
            if file_node.is_dir():
 
                raise RepositoryError('given path is a directory')
 
        except RepositoryError, e:
 
            h.flash(str(e), category='warning')
 
            redirect(h.url('files_home', repo_name=repo_name,
 
                           revision=cs.raw_id))
 

	
 
        return file_node
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def index(self, repo_name, revision, f_path, annotate=False):
 
        # redirect to given revision from form if given
 
        post_revision = request.POST.get('at_rev', None)
 
        if post_revision:
 
            cs = self.__get_cs_or_redirect(post_revision, repo_name)
 
            redirect(url('files_home', repo_name=c.repo_name,
 
                         revision=cs.raw_id, f_path=f_path))
 

	
 
        c.changeset = self.__get_cs_or_redirect(revision, repo_name)
 
        c.branch = request.GET.get('branch', None)
 
        c.f_path = f_path
 
        c.annotate = annotate
 
        c.changeset = self.__get_cs_or_redirect(revision, repo_name)
 
        cur_rev = c.changeset.revision
 

	
 
        # prev link
 
        try:
 
            prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
 
            c.url_prev = url('files_home', repo_name=c.repo_name,
 
                         revision=prev_rev.raw_id, f_path=f_path)
 
            if c.branch:
 
                c.url_prev += '?branch=%s' % c.branch
 
        except (ChangesetDoesNotExistError, VCSError):
 
            c.url_prev = '#'
 

	
 
        # next link
 
        try:
 
            next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
 
            c.url_next = url('files_home', repo_name=c.repo_name,
 
                     revision=next_rev.raw_id, f_path=f_path)
 
            if c.branch:
 
                c.url_next += '?branch=%s' % c.branch
 
        except (ChangesetDoesNotExistError, VCSError):
 
            c.url_next = '#'
 

	
 
        # files or dirs
 
        try:
 
            c.file = c.changeset.get_node(f_path)
 

	
 
            if c.file.is_file():
 
                c.load_full_history = False
 
                file_last_cs = c.file.last_changeset
 
                c.file_changeset = (c.changeset
 
                                    if c.changeset.revision < file_last_cs.revision
 
                                    else file_last_cs)
 
                #determine if we're on branch head
 
                _branches = c.rhodecode_repo.branches
 
                c.on_branch_head = revision in _branches.keys() + _branches.values() 
 
                c.on_branch_head = revision in _branches.keys() + _branches.values()
 
                _hist = []
 
                c.file_history = []
 
                if c.load_full_history:
 
                    c.file_history, _hist = self._get_node_history(c.changeset, f_path)
 

	
 
                c.authors = []
 
                for a in set([x.author for x in _hist]):
 
                    c.authors.append((h.email(a), h.person(a)))
 
            else:
 
                c.authors = c.file_history = []
 
        except RepositoryError, e:
 
            h.flash(str(e), category='warning')
 
            redirect(h.url('files_home', repo_name=repo_name,
 
                           revision='tip'))
 

	
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return render('files/files_ypjax.html')
 

	
 
        return render('files/files.html')
 

	
 
    def history(self, repo_name, revision, f_path, annotate=False):
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            c.changeset = self.__get_cs_or_redirect(revision, repo_name)
 
            c.f_path = f_path
 
            c.annotate = annotate
 
            c.file = c.changeset.get_node(f_path)
 
            if c.file.is_file():
 
                file_last_cs = c.file.last_changeset
 
                c.file_changeset = (c.changeset
 
                                    if c.changeset.revision < file_last_cs.revision
 
                                    else file_last_cs)
 
                c.file_history, _hist = self._get_node_history(c.changeset, f_path)
 
                c.authors = []
 
                for a in set([x.author for x in _hist]):
 
                    c.authors.append((h.email(a), h.person(a)))
 
                return render('files/files_history_box.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def rawfile(self, repo_name, revision, f_path):
 
        cs = self.__get_cs_or_redirect(revision, repo_name)
 
        file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
 

	
 
        response.content_disposition = 'attachment; filename=%s' % \
 
            safe_str(f_path.split(Repository.url_sep())[-1])
 

	
 
        response.content_type = file_node.mimetype
 
        return file_node.content
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def raw(self, repo_name, revision, f_path):
 
        cs = self.__get_cs_or_redirect(revision, repo_name)
 
        file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
 

	
 
        raw_mimetype_mapping = {
 
            # map original mimetype to a mimetype used for "show as raw"
 
            # you can also provide a content-disposition to override the
 
            # default "attachment" disposition.
 
            # orig_type: (new_type, new_dispo)
 

	
 
            # show images inline:
 
            'image/x-icon': ('image/x-icon', 'inline'),
 
            'image/png': ('image/png', 'inline'),
 
            'image/gif': ('image/gif', 'inline'),
 
            'image/jpeg': ('image/jpeg', 'inline'),
 
            'image/svg+xml': ('image/svg+xml', 'inline'),
 
        }
 

	
 
        mimetype = file_node.mimetype
 
        try:
 
            mimetype, dispo = raw_mimetype_mapping[mimetype]
 
        except KeyError:
 
            # we don't know anything special about this, handle it safely
 
            if file_node.is_binary:
 
                # do same as download raw for binary files
 
                mimetype, dispo = 'application/octet-stream', 'attachment'
 
            else:
 
                # do not just use the original mimetype, but force text/plain,
 
                # otherwise it would serve text/html and that might be unsafe.
 
                # Note: underlying vcs library fakes text/plain mimetype if the
 
                # mimetype can not be determined and it thinks it is not
 
                # binary.This might lead to erroneous text display in some
 
                # cases, but helps in other cases, like with text files
 
                # without extension.
 
                mimetype, dispo = 'text/plain', 'inline'
 

	
 
        if dispo == 'attachment':
 
            dispo = 'attachment; filename=%s' % \
 
                        safe_str(f_path.split(os.sep)[-1])
 

	
 
        response.content_disposition = dispo
 
        response.content_type = mimetype
 
        return file_node.content
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def edit(self, repo_name, revision, f_path):
 
        repo = c.rhodecode_db_repo
 
        if repo.enable_locking and repo.locked[0]:
 
            h.flash(_('This repository is has been locked by %s on %s')
 
                % (h.person_by_id(repo.locked[0]),
 
                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
 
                  'warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip'))
 

	
 
        # check if revision is a branch identifier- basically we cannot
 
        # create multiple heads via file editing
 
        _branches = repo.scm_instance.branches
 
        # check if revision is a branch name or branch hash
 
        if revision not in _branches.keys() + _branches.values():
 
            h.flash(_('You can only edit files with revision '
 
                      'being a valid branch '), category='warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip',
 
                                  f_path=f_path))
 

	
 
        r_post = request.POST
 

	
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name)
 
        c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
 

	
 
        if c.file.is_binary:
 
            return redirect(url('files_home', repo_name=c.repo_name,
 
                         revision=c.cs.raw_id, f_path=f_path))
 
        c.default_message = _('Edited file %s via RhodeCode') % (f_path)
 
        c.f_path = f_path
 

	
 
        if r_post:
 

	
 
            old_content = c.file.content
 
            sl = old_content.splitlines(1)
 
            first_line = sl[0] if sl else ''
 
            # modes:  0 - Unix, 1 - Mac, 2 - DOS
 
            mode = detect_mode(first_line, 0)
 
            content = convert_line_endings(r_post.get('content'), mode)
 

	
 
            message = r_post.get('message') or c.default_message
 
            author = self.rhodecode_user.full_contact
 

	
 
            if content == old_content:
 
                h.flash(_('No changes'),
 
                    category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            try:
 
                self.scm_model.commit_change(repo=c.rhodecode_repo,
 
                                             repo_name=repo_name, cs=c.cs,
 
                                             user=self.rhodecode_user,
 
                                             author=author, message=message,
 
                                             content=content, f_path=f_path)
 
                h.flash(_('Successfully committed to %s') % f_path,
 
                        category='success')
 

	
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                h.flash(_('Error occurred during commit'), category='error')
 
            return redirect(url('changeset_home',
 
                                repo_name=c.repo_name, revision='tip'))
 

	
 
        return render('files/files_edit.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def add(self, repo_name, revision, f_path):
 

	
 
        repo = Repository.get_by_repo_name(repo_name)
 
        if repo.enable_locking and repo.locked[0]:
 
            h.flash(_('This repository is has been locked by %s on %s')
 
                % (h.person_by_id(repo.locked[0]),
 
                   h.fmt_date(h.time_to_datetime(repo.locked[1]))),
 
                  'warning')
 
            return redirect(h.url('files_home',
 
                                  repo_name=repo_name, revision='tip'))
 

	
 
        r_post = request.POST
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name,
 
                                         redirect_after=False)
 
        if c.cs is None:
 
            c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias)
 
        c.default_message = (_('Added file via RhodeCode'))
 
        c.f_path = f_path
 

	
 
        if r_post:
 
            unix_mode = 0
 
            content = convert_line_endings(r_post.get('content'), unix_mode)
 

	
 
            message = r_post.get('message') or c.default_message
 
            location = r_post.get('location')
 
            filename = r_post.get('filename')
 
            file_obj = r_post.get('upload_file', None)
 

	
 
            if file_obj is not None and hasattr(file_obj, 'filename'):
 
                filename = file_obj.filename
 
                content = file_obj.file
 

	
 
            node_path = os.path.join(location, filename)
 
            author = self.rhodecode_user.full_contact
 

	
 
            if not content:
 
                h.flash(_('No content'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            if not filename:
 
                h.flash(_('No filename'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 

	
 
            try:
 
                self.scm_model.create_node(repo=c.rhodecode_repo,
 
                                           repo_name=repo_name, cs=c.cs,
 
                                           user=self.rhodecode_user,
 
                                           author=author, message=message,
 
                                           content=content, f_path=node_path)
 
                h.flash(_('Successfully committed to %s') % node_path,
 
                        category='success')
 
            except NodeAlreadyExistsError, e:
 
                h.flash(_(e), category='error')
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                h.flash(_('Error occurred during commit'), category='error')
 
            return redirect(url('changeset_home',
 
                                repo_name=c.repo_name, revision='tip'))
 

	
 
        return render('files/files_add.html')
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def archivefile(self, repo_name, fname):
 

	
 
        fileformat = None
 
        revision = None
 
        ext = None
 
        subrepos = request.GET.get('subrepos') == 'true'
 

	
 
        for a_type, ext_data in settings.ARCHIVE_SPECS.items():
 
            archive_spec = fname.split(ext_data[1])
 
            if len(archive_spec) == 2 and archive_spec[1] == '':
 
                fileformat = a_type or ext_data[1]
 
                revision = archive_spec[0]
 
                ext = ext_data[1]
 

	
 
        try:
 
            dbrepo = RepoModel().get_by_repo_name(repo_name)
 
            if dbrepo.enable_downloads is False:
 
                return _('downloads disabled')
 

	
 
            if c.rhodecode_repo.alias == 'hg':
 
                # patch and reset hooks section of UI config to not run any
 
                # hooks on fetching archives with subrepos
 
                for k, v in c.rhodecode_repo._repo.ui.configitems('hooks'):
 
                    c.rhodecode_repo._repo.ui.setconfig('hooks', k, None)
 

	
 
            cs = c.rhodecode_repo.get_changeset(revision)
 
            content_type = settings.ARCHIVE_SPECS[fileformat][0]
 
        except ChangesetDoesNotExistError:
 
            return _('Unknown revision %s') % revision
 
        except EmptyRepositoryError:
 
            return _('Empty repository')
 
        except (ImproperArchiveTypeError, KeyError):
 
            return _('Unknown archive type')
 

	
 
        fd, archive = tempfile.mkstemp()
 
        t = open(archive, 'wb')
 
        cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
 
        t.close()
 

	
 
        def get_chunked_archive(archive):
 
            stream = open(archive, 'rb')
 
            while True:
 
                data = stream.read(16 * 1024)
 
                if not data:
 
                    stream.close()
 
                    os.close(fd)
 
                    os.remove(archive)
 
                    break
 
                yield data
 

	
 
        response.content_disposition = str('attachment; filename=%s-%s%s' \
 
                                           % (repo_name, revision[:12], ext))
 
        response.content_type = str(content_type)
 
        return get_chunked_archive(archive)
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def diff(self, repo_name, f_path):
 
        ignore_whitespace = request.GET.get('ignorews') == '1'
 
        line_context = request.GET.get('context', 3)
 
        diff1 = request.GET.get('diff1', '')
 
        diff2 = request.GET.get('diff2', '')
 
        c.action = request.GET.get('diff')
 
        c.no_changes = diff1 == diff2
 
        c.f_path = f_path
 
        c.big_diff = False
 
        c.anchor_url = anchor_url
 
        c.ignorews_url = _ignorews_url
 
        c.context_url = _context_url
 
        c.changes = OrderedDict()
 
        c.changes[diff2] = []
 

	
 
        #special case if we want a show rev only, it's impl here
 
        #to reduce JS and callbacks
 

	
 
        if request.GET.get('show_rev'):
 
            if str2bool(request.GET.get('annotate', 'False')):
 
                _url = url('files_annotate_home', repo_name=c.repo_name,
 
                           revision=diff1, f_path=c.f_path)
 
            else:
 
                _url = url('files_home', repo_name=c.repo_name,
 
                           revision=diff1, f_path=c.f_path)
 

	
 
            return redirect(_url)
 
        try:
 
            if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
 
                c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
 
                try:
 
                    node1 = c.changeset_1.get_node(f_path)
 
                except NodeDoesNotExistError:
 
                    c.changeset_1 = EmptyChangeset(cs=diff1,
 
                                                   revision=c.changeset_1.revision,
 
                                                   repo=c.rhodecode_repo)
 
                    node1 = FileNode(f_path, '', changeset=c.changeset_1)
 
            else:
 
                c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
 
                node1 = FileNode(f_path, '', changeset=c.changeset_1)
 

	
 
            if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
 
                c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
 
                try:
 
                    node2 = c.changeset_2.get_node(f_path)
 
                except NodeDoesNotExistError:
 
                    c.changeset_2 = EmptyChangeset(cs=diff2,
 
                                                   revision=c.changeset_2.revision,
 
                                                   repo=c.rhodecode_repo)
 
                    node2 = FileNode(f_path, '', changeset=c.changeset_2)
 
            else:
 
                c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
 
                node2 = FileNode(f_path, '', changeset=c.changeset_2)
 
        except (RepositoryError, NodeError):
 
            log.error(traceback.format_exc())
 
            return redirect(url('files_home', repo_name=c.repo_name,
 
                                f_path=f_path))
 

	
 
        if c.action == 'download':
 
            _diff = diffs.get_gitdiff(node1, node2,
 
                                      ignore_whitespace=ignore_whitespace,
 
                                      context=line_context)
 
            diff = diffs.DiffProcessor(_diff, format='gitdiff')
 

	
 
            diff_name = '%s_vs_%s.diff' % (diff1, diff2)
 
            response.content_type = 'text/plain'
 
            response.content_disposition = (
 
                'attachment; filename=%s' % diff_name
 
            )
 
            return diff.as_raw()
 

	
 
        elif c.action == 'raw':
 
            _diff = diffs.get_gitdiff(node1, node2,
 
                                      ignore_whitespace=ignore_whitespace,
 
                                      context=line_context)
 
            diff = diffs.DiffProcessor(_diff, format='gitdiff')
 
            response.content_type = 'text/plain'
 
            return diff.as_raw()
 

	
 
        else:
 
            fid = h.FID(diff2, node2.path)
 
            line_context_lcl = get_line_ctx(fid, request.GET)
 
            ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
 

	
 
            lim = request.GET.get('fulldiff') or self.cut_off_limit
 
            _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1,
 
                                         filenode_new=node2,
 
                                         cut_off_limit=lim,
 
                                         ignore_whitespace=ign_whitespace_lcl,
 
                                         line_context=line_context_lcl,
 
                                         enable_comments=False)
 
            op = ''
 
            filename = node1.path
 
            cs_changes = {
 
                'fid': [cs1, cs2, op, filename, diff, st]
 
            }
 
            c.changes = cs_changes
 

	
 
        return render('files/file_diff.html')
 

	
 
    def _get_node_history(self, cs, f_path, changesets=None):
 
        """
 
        get changesets history for given node
 

	
 
        :param cs: changeset to calculate history
 
        :param f_path: path for node to calculate history for
 
        :param changesets: if passed don't calculate history and take
 
            changesets defined in this list
 
        """
 
        # calculate history based on tip
 
        tip_cs = c.rhodecode_repo.get_changeset()
 
        if changesets is None:
 
            try:
 
                changesets = tip_cs.get_file_history(f_path)
 
            except (NodeDoesNotExistError, ChangesetError):
 
                #this node is not present at tip !
 
                changesets = cs.get_file_history(f_path)
 
        hist_l = []
 

	
 
        changesets_group = ([], _("Changesets"))
 
        branches_group = ([], _("Branches"))
 
        tags_group = ([], _("Tags"))
 
        _hg = cs.repository.alias == 'hg'
 
        for chs in changesets:
 
            #_branch = '(%s)' % chs.branch if _hg else ''
 
            _branch = chs.branch
 
            n_desc = 'r%s:%s (%s)' % (chs.revision, chs.short_id, _branch)
 
            changesets_group[0].append((chs.raw_id, n_desc,))
 
        hist_l.append(changesets_group)
 

	
 
        for name, chs in c.rhodecode_repo.branches.items():
 
            branches_group[0].append((chs, name),)
 
        hist_l.append(branches_group)
 

	
 
        for name, chs in c.rhodecode_repo.tags.items():
 
            tags_group[0].append((chs, name),)
 
        hist_l.append(tags_group)
 

	
 
        return hist_l, changesets
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def nodelist(self, repo_name, revision, f_path):
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            cs = self.__get_cs_or_redirect(revision, repo_name)
 
            _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path,
 
                                          flat=False)
 
            return {'nodes': _d + _f}
rhodecode/model/db.py
Show inline comments
 
@@ -335,1650 +335,1650 @@ class User(Base, BaseModel):
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
 

	
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 

	
 
    notifications = relationship('UserNotification', cascade='all')
 
    # notifications assigned to this user
 
    user_created_notifications = relationship('Notification', cascade='all')
 
    # comments created by this user
 
    user_comments = relationship('ChangesetComment', cascade='all')
 
    #extra emails for this user
 
    user_emails = relationship('UserEmailMap', cascade='all')
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 
    @property
 
    def firstname(self):
 
        # alias for future
 
        return self.name
 

	
 
    @property
 
    def emails(self):
 
        other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
 
        return [self.email] + [x.email for x in other]
 

	
 
    @property
 
    def ip_addresses(self):
 
        ret = UserIpMap.query().filter(UserIpMap.user == self).all()
 
        return [x.ip_addr for x in ret]
 

	
 
    @property
 
    def username_and_name(self):
 
        return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.firstname, self.lastname)
 
                if (self.firstname and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    def __unicode__(self):
 
        return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                     self.user_id, self.username)
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.email.ilike(email))
 
        else:
 
            q = cls.query().filter(cls.email == email)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_email_key_%s" % email))
 

	
 
        ret = q.scalar()
 
        if ret is None:
 
            q = UserEmailMap.query()
 
            # try fetching in alternate email map
 
            if case_insensitive:
 
                q = q.filter(UserEmailMap.email.ilike(email))
 
            else:
 
                q = q.filter(UserEmailMap.email == email)
 
            q = q.options(joinedload(UserEmailMap.user))
 
            if cache:
 
                q = q.options(FromCache("sql_cache_short",
 
                                        "get_email_map_key_%s" % email))
 
            ret = getattr(q.scalar(), 'user', None)
 

	
 
        return ret
 

	
 
    @classmethod
 
    def get_from_cs_author(cls, author):
 
        """
 
        Tries to get User objects out of commit author string
 

	
 
        :param author:
 
        """
 
        from rhodecode.lib.helpers import email, author_name
 
        # Valid email in the attribute passed, see if they're in the system
 
        _email = email(author)
 
        if _email:
 
            user = cls.get_by_email(_email, case_insensitive=True)
 
            if user:
 
                return user
 
        # Maybe we can match by username?
 
        _author = author_name(author)
 
        user = cls.get_by_username(_author, case_insensitive=True)
 
        if user:
 
            return user
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 
        self.last_login = datetime.datetime.now()
 
        Session().add(self)
 
        log.debug('updated user %s lastlogin' % self.username)
 

	
 
    def get_api_data(self):
 
        """
 
        Common function for generating user related data for API
 
        """
 
        user = self
 
        data = dict(
 
            user_id=user.user_id,
 
            username=user.username,
 
            firstname=user.name,
 
            lastname=user.lastname,
 
            email=user.email,
 
            emails=user.emails,
 
            api_key=user.api_key,
 
            active=user.active,
 
            admin=user.admin,
 
            ldap_dn=user.ldap_dn,
 
            last_login=user.last_login,
 
            ip_addresses=user.ip_addresses
 
        )
 
        return data
 

	
 
    def __json__(self):
 
        data = dict(
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 
        data.update(self.get_api_data())
 
        return data
 

	
 

	
 
class UserEmailMap(Base, BaseModel):
 
    __tablename__ = 'user_email_map'
 
    __table_args__ = (
 
        Index('uem_email_idx', 'email'),
 
        UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    user = relationship('User', lazy='joined')
 

	
 
    @validates('_email')
 
    def validate_email(self, key, email):
 
        # check if this email is not main one
 
        main_email = Session().query(User).filter(User.email == email).scalar()
 
        if main_email is not None:
 
            raise AttributeError('email %s is present is user table' % email)
 
        return email
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 

	
 
class UserIpMap(Base, BaseModel):
 
    __tablename__ = 'user_ip_map'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'ip_addr'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    user = relationship('User', lazy='joined')
 

	
 
    @classmethod
 
    def _get_ip_range(cls, ip_addr):
 
        from rhodecode.lib import ipaddr
 
        net = ipaddr.IPNetwork(address=ip_addr)
 
        return [str(net.network), str(net.broadcast)]
 

	
 
    def __json__(self):
 
        return dict(
 
          ip_addr=self.ip_addr,
 
          ip_range=self._get_ip_range(self.ip_addr)
 
        )
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
 
    repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository', cascade='')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    def get_api_data(self):
 
        users_group = self
 

	
 
        data = dict(
 
            users_group_id=users_group.users_group_id,
 
            group_name=users_group.users_group_name,
 
            active=users_group.users_group_active,
 
        )
 

	
 
        return data
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        Index('r_repo_name_idx', 'repo_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
    _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing',
 
                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
 
                             cascade='all')
 

	
 
    logs = relationship('UserLog')
 
    comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_org = relationship('PullRequest',
 
                    primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_other = relationship('PullRequest',
 
                    primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
 
                                   self.repo_name)
 

	
 
    @hybrid_property
 
    def locked(self):
 
        # always should return [user_id, timelocked]
 
        if self._locked:
 
            _lock_info = self._locked.split(':')
 
            return int(_lock_info[0]), _lock_info[1]
 
        return [None, None]
 

	
 
    @locked.setter
 
    def locked(self, val):
 
        if val and isinstance(val, (list, tuple)):
 
            self._locked = ':'.join(map(str, val))
 
        else:
 
            self._locked = None
 

	
 
    @hybrid_property
 
    def changeset_cache(self):
 
        from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
        dummy = EmptyChangeset().__json__()
 
        if not self._changeset_cache:
 
            return dummy
 
        try:
 
            return json.loads(self._changeset_cache)
 
        except TypeError:
 
            return dummy
 

	
 
    @changeset_cache.setter
 
    def changeset_cache(self, val):
 
        try:
 
            self._changeset_cache = json.dumps(val)
 
        except:
 
            log.error(traceback.format_exc())
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def normalize_repo_name(cls, repo_name):
 
        """
 
        Normalizes os specific repo_name to the format internally stored inside
 
        dabatabase using URL_SEP
 

	
 
        :param cls:
 
        :param repo_name:
 
        """
 
        return cls.url_sep().join(repo_name.split(os.sep))
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_full_path(cls, repo_full_path):
 
        repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
 
        repo_name = cls.normalize_repo_name(repo_name)
 
        return cls.get_by_repo_name(repo_name.strip(URL_SEP))
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session().query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def forks(self):
 
        """
 
        Return forks of this repo
 
        """
 
        return Repository.get_repo_forks(self.repo_id)
 

	
 
    @property
 
    def parent(self):
 
        """
 
        Returns fork parent
 
        """
 
        return self.fork
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    def groups_with_parents(self):
 
        groups = []
 
        if self.group is None:
 
            return groups
 

	
 
        cur_gr = self.group
 
        groups.insert(0, cur_gr)
 
        while 1:
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            groups.insert(0, gr)
 

	
 
        return groups
 

	
 
    @property
 
    def groups_and_repo(self):
 
        return self.groups_with_parents, self.just_name
 

	
 
    @LazyProperty
 
    def repo_path(self):
 
        """
 
        Returns base full path for that repository means where it actually
 
        exists on a filesystem
 
        """
 
        q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              Repository.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def repo_full_path(self):
 
        p = [self.repo_path]
 
        # we need to split the name by / since this is how we store the
 
        # names in the database, but that eventually needs to be converted
 
        # into a valid system path
 
        p += self.repo_name.split(Repository.url_sep())
 
        return os.path.join(*p)
 

	
 
    @property
 
    def cache_keys(self):
 
        """
 
        Returns associated cache keys for that repo
 
        """
 
        return CacheInvalidation.query()\
 
            .filter(CacheInvalidation.cache_args == self.repo_name)\
 
            .order_by(CacheInvalidation.cache_key)\
 
            .all()
 

	
 
    def get_new_name(self, repo_name):
 
        """
 
        returns new full repository name based on assigned group and new new
 

	
 
        :param group_name:
 
        """
 
        path_prefix = self.group.full_path_splitted if self.group else []
 
        return Repository.url_sep().join(path_prefix + [repo_name])
 

	
 
    @property
 
    def _ui(self):
 
        """
 
        Creates an db based ui object for this repository
 
        """
 
        from rhodecode.lib.utils import make_ui
 
        return make_ui('db', clear_session=False)
 

	
 
    @classmethod
 
    def inject_ui(cls, repo, extras={}):
 
        from rhodecode.lib.vcs.backends.hg import MercurialRepository
 
        from rhodecode.lib.vcs.backends.git import GitRepository
 
        required = (MercurialRepository, GitRepository)
 
        if not isinstance(repo, required):
 
            raise Exception('repo must be instance of %s' % required)
 

	
 
        # inject ui extra param to log this action via push logger
 
        for k, v in extras.items():
 
            repo._repo.ui.setconfig('rhodecode_extras', k, v)
 

	
 
    @classmethod
 
    def is_valid(cls, repo_name):
 
        """
 
        returns True if given repo name is a valid filesystem repository
 

	
 
        :param cls:
 
        :param repo_name:
 
        """
 
        from rhodecode.lib.utils import is_valid_repo
 

	
 
        return is_valid_repo(repo_name, cls.base_path())
 

	
 
    def get_api_data(self):
 
        """
 
        Common function for generating repo api data
 

	
 
        """
 
        repo = self
 
        data = dict(
 
            repo_id=repo.repo_id,
 
            repo_name=repo.repo_name,
 
            repo_type=repo.repo_type,
 
            clone_uri=repo.clone_uri,
 
            private=repo.private,
 
            created_on=repo.created_on,
 
            description=repo.description,
 
            landing_rev=repo.landing_rev,
 
            owner=repo.user.username,
 
            fork_of=repo.fork.repo_name if repo.fork else None,
 
            enable_statistics=repo.enable_statistics,
 
            enable_locking=repo.enable_locking,
 
            enable_downloads=repo.enable_downloads,
 
            last_changeset=repo.changeset_cache
 
        )
 

	
 
        return data
 

	
 
    @classmethod
 
    def lock(cls, repo, user_id):
 
        repo.locked = [user_id, time.time()]
 
        Session().add(repo)
 
        Session().commit()
 

	
 
    @classmethod
 
    def unlock(cls, repo):
 
        repo.locked = None
 
        Session().add(repo)
 
        Session().commit()
 

	
 
    @property
 
    def last_db_change(self):
 
        return self.updated_on
 

	
 
    def clone_url(self, **override):
 
        from pylons import url
 
        from urlparse import urlparse
 
        import urllib
 
        parsed_url = urlparse(url('home', qualified=True))
 
        default_clone_uri = '%(scheme)s://%(user)s%(pass)s%(netloc)s%(prefix)s%(path)s'
 
        decoded_path = safe_unicode(urllib.unquote(parsed_url.path))
 
        args = {
 
           'user': '',
 
           'pass': '',
 
           'scheme': parsed_url.scheme,
 
           'netloc': parsed_url.netloc,
 
           'prefix': decoded_path,
 
           'path': self.repo_name
 
        }
 

	
 
        args.update(override)
 
        return default_clone_uri % args
 

	
 
    #==========================================================================
 
    # SCM PROPERTIES
 
    #==========================================================================
 

	
 
    def get_changeset(self, rev=None):
 
        return get_changeset_safe(self.scm_instance, rev)
 

	
 
    def get_landing_changeset(self):
 
        """
 
        Returns landing changeset, or if that doesn't exist returns the tip
 
        """
 
        cs = self.get_changeset(self.landing_rev) or self.get_changeset()
 
        return cs
 

	
 
    def update_changeset_cache(self, cs_cache=None):
 
        """
 
        Update cache of last changeset for repository, keys should be::
 

	
 
            short_id
 
            raw_id
 
            revision
 
            message
 
            date
 
            author
 

	
 
        :param cs_cache:
 
        """
 
        from rhodecode.lib.vcs.backends.base import BaseChangeset
 
        if cs_cache is None:
 
            cs_cache = self.get_changeset()
 
        if isinstance(cs_cache, BaseChangeset):
 
            cs_cache = cs_cache.__json__()
 

	
 
        if (cs_cache != self.changeset_cache
 
            or not self.last_change
 
            or not self.changeset_cache):
 
            _default = datetime.datetime.fromtimestamp(0)
 
            last_change = cs_cache.get('date') or self.last_change or _default
 
            log.debug('updated repo %s with new cs cache %s' % (self, cs_cache))
 
            self.updated_on = last_change
 
            self.changeset_cache = cs_cache
 
            Session().add(self)
 
            Session().commit()
 
        else:
 
            log.debug('Skipping repo:%s already with latest changes' % self)
 

	
 
    @property
 
    def tip(self):
 
        return self.get_changeset('tip')
 

	
 
    @property
 
    def author(self):
 
        return self.tip.author
 

	
 
    @property
 
    def last_change(self):
 
        return self.scm_instance.last_change
 

	
 
    def get_comments(self, revisions=None):
 
        """
 
        Returns comments for this repository grouped by revisions
 

	
 
        :param revisions: filter query by revisions only
 
        """
 
        cmts = ChangesetComment.query()\
 
            .filter(ChangesetComment.repo == self)
 
        if revisions:
 
            cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
 
        grouped = defaultdict(list)
 
        for cmt in cmts.all():
 
            grouped[cmt.revision].append(cmt)
 
        return grouped
 

	
 
    def statuses(self, revisions=None):
 
        """
 
        Returns statuses for this repository
 

	
 
        :param revisions: list of revisions to get statuses for
 
        :type revisions: list
 
        """
 

	
 
        statuses = ChangesetStatus.query()\
 
            .filter(ChangesetStatus.repo == self)\
 
            .filter(ChangesetStatus.version == 0)
 
        if revisions:
 
            statuses = statuses.filter(ChangesetStatus.revision.in_(revisions))
 
        grouped = {}
 

	
 
        #maybe we have open new pullrequest without a status ?
 
        stat = ChangesetStatus.STATUS_UNDER_REVIEW
 
        status_lbl = ChangesetStatus.get_status_lbl(stat)
 
        for pr in PullRequest.query().filter(PullRequest.org_repo == self).all():
 
            for rev in pr.revisions:
 
                pr_id = pr.pull_request_id
 
                pr_repo = pr.other_repo.repo_name
 
                grouped[rev] = [stat, status_lbl, pr_id, pr_repo]
 

	
 
        for stat in statuses.all():
 
            pr_id = pr_repo = None
 
            if stat.pull_request:
 
                pr_id = stat.pull_request.pull_request_id
 
                pr_repo = stat.pull_request.other_repo.repo_name
 
            grouped[stat.revision] = [str(stat.status), stat.status_lbl,
 
                                      pr_id, pr_repo]
 
        return grouped
 

	
 
    def _repo_size(self):
 
        from rhodecode.lib import helpers as h
 
        log.debug('calculating repository size...')
 
        return h.format_byte_size(self.scm_instance.size)
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(repo_name=self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        import rhodecode
 
        full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, cache_map=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 

	
 
        if cache_map:
 
            # get using prefilled cache_map
 
            invalidate_repo = cache_map[self.repo_name]
 
            if invalidate_repo:
 
                invalidate_repo = (None if invalidate_repo.cache_active
 
                                   else invalidate_repo)
 
        else:
 
            # get from invalidate
 
            invalidate_repo = self.invalidate
 

	
 
        if invalidate_repo is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(invalidate_repo.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository' % alias)
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    __mapper_args__ = {'order_by': 'group_name'}
 

	
 
    group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
 
    group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
 

	
 
    parent_group = relationship('RepoGroup', remote_side=group_id)
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @classmethod
 
    def groups_choices(cls, groups=None, show_empty_group=True):
 
        from webhelpers.html import literal as _literal
 
        if not groups:
 
            groups = cls.query().all()
 

	
 
        repo_groups = []
 
        if show_empty_group:
 
            repo_groups = [('-1', '-- no parent --')]
 
        sep = ' &raquo; '
 
        _name = lambda k: _literal(sep.join(k))
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in groups])
 

	
 
        repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
 
        return repo_groups
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_group_%s" % _hash_key(group_name)
 
                            )
 
            )
 
        return gr.scalar()
 

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return RepoGroup.query().filter(RepoGroup.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(RepoGroup.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query()\
 
                .filter(Repository.group == self)\
 
                .order_by(Repository.repo_name)
 

	
 
    @property
 
    def repositories_recursive_count(self):
 
        cnt = self.repositories.count()
 

	
 
        def children_count(group):
 
            cnt = 0
 
            for child in group.children:
 
                cnt += child.repositories.count()
 
                cnt += children_count(child)
 
            return cnt
 

	
 
        return cnt + children_count(self)
 

	
 
    def recursive_groups_and_repos(self):
 
        """
 
        Recursive return all groups, with repositories in those groups
 
        """
 
        all_ = []
 

	
 
        def _get_members(root_gr):
 
            for r in root_gr.repositories:
 
                all_.append(r)
 
            childs = root_gr.children.all()
 
            if childs:
 
                for gr in childs:
 
                    all_.append(gr)
 
                    _get_members(gr)
 

	
 
        _get_members(self)
 
        return [self] + all_
 

	
 
    def get_new_name(self, group_name):
 
        """
 
        returns new full group name based on parent and new name
 

	
 
        :param group_name:
 
        """
 
        path_prefix = (self.parent_group.full_path_splitted if
 
                       self.parent_group else [])
 
        return RepoGroup.url_sep().join(path_prefix + [group_name])
 

	
 

	
 
class Permission(Base, BaseModel):
 
    __tablename__ = 'permissions'
 
    __table_args__ = (
 
        Index('p_perm_name_idx', 'permission_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    PERMS = [
 
        ('repository.none', _('Repository no access')),
 
        ('repository.read', _('Repository read access')),
 
        ('repository.write', _('Repository write access')),
 
        ('repository.admin', _('Repository admin access')),
 

	
 
        ('group.none', _('Repositories Group no access')),
 
        ('group.read', _('Repositories Group read access')),
 
        ('group.write', _('Repositories Group write access')),
 
        ('group.admin', _('Repositories Group admin access')),
 

	
 
        ('hg.admin', _('RhodeCode Administrator')),
 
        ('hg.create.none', _('Repository creation disabled')),
 
        ('hg.create.repository', _('Repository creation enabled')),
 
        ('hg.fork.none', _('Repository forking disabled')),
 
        ('hg.fork.repository', _('Repository forking enabled')),
 
        ('hg.register.none', _('Register disabled')),
 
        ('hg.register.manual_activate', _('Register new user with RhodeCode '
 
                                          'with manual activation')),
 

	
 
        ('hg.register.auto_activate', _('Register new user with RhodeCode '
 
                                        'with auto activation')),
 
    ]
 

	
 
    # defines which permissions are more important higher the more important
 
    PERM_WEIGHTS = {
 
        'repository.none': 0,
 
        'repository.read': 1,
 
        'repository.write': 3,
 
        'repository.admin': 4,
 

	
 
        'group.none': 0,
 
        'group.read': 1,
 
        'group.write': 3,
 
        'group.admin': 4,
 

	
 
        'hg.fork.none': 0,
 
        'hg.fork.repository': 1,
 
        'hg.create.none': 0,
 
        'hg.create.repository':1
 
    }
 

	
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__, self.permission_id, self.permission_name
 
        )
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session().query(UserRepoToPerm, Repository, cls)\
 
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (
 
         UniqueConstraint('repository_id'),
 
         {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
          'mysql_charset': 'utf8'}
 
    )
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'follows_repository_id'),
 
        UniqueConstraint('user_id', 'follows_user_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (
 
        UniqueConstraint('cache_key'),
 
        Index('key_idx', 'cache_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.cache_id, self.cache_key)
 

	
 
    @property
 
    def prefix(self):
 
        _split = self.cache_key.split(self.cache_args, 1)
 
        if _split and len(_split) == 2:
 
            return _split[0]
 
        return ''
 

	
 
    @classmethod
 
    def clear_cache(cls):
 
        cls.query().delete()
 

	
 
    @classmethod
 
    def _get_key(cls, key):
 
        """
 
        Wrapper for generating a key, together with a prefix
 

	
 
        :param key:
 
        """
 
        import rhodecode
 
        prefix = ''
 
        org_key = key
 
        iid = rhodecode.CONFIG.get('instance_id')
 
        if iid:
 
            prefix = iid
 

	
 
        return "%s%s" % (prefix, key), prefix, org_key
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.cache_key == key).scalar()
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        return cls.query().filter(cls.cache_args == repo_name).all()
 

	
 
    @classmethod
 
    def _get_or_create_key(cls, key, repo_name, commit=True):
 
        inv_obj = Session().query(cls).filter(cls.cache_key == key).scalar()
 
        if not inv_obj:
 
            try:
 
                inv_obj = CacheInvalidation(key, repo_name)
 
                Session().add(inv_obj)
 
                if commit:
 
                    Session().commit()
 
            except Exception:
 
                log.error(traceback.format_exc())
 
                Session().rollback()
 
        return inv_obj
 

	
 
    @classmethod
 
    def invalidate(cls, key):
 
        """
 
        Returns Invalidation object if this given key should be invalidated
 
        None otherwise. `cache_active = False` means that this cache
 
        state is not valid and needs to be invalidated
 

	
 
        :param key:
 
        """
 
        repo_name = key
 
        repo_name = remove_suffix(repo_name, '_README')
 
        repo_name = remove_suffix(repo_name, '_RSS')
 
        repo_name = remove_suffix(repo_name, '_ATOM')
 

	
 
        # adds instance prefix
 
        key, _prefix, _org_key = cls._get_key(key)
 
        inv = cls._get_or_create_key(key, repo_name)
 

	
 
        if inv and inv.cache_active is False:
 
            return inv
 

	
 
    @classmethod
 
    def set_invalidate(cls, key=None, repo_name=None):
 
        """
 
        Mark this Cache key for invalidation, either by key or whole
 
        cache sets based on repo_name
 

	
 
        :param key:
 
        """
 
        invalidated_keys = []
 
        if key:
 
            key, _prefix, _org_key = cls._get_key(key)
 
            inv_objs = Session().query(cls).filter(cls.cache_key == key).all()
 
        elif repo_name:
 
            inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all()
 

	
 
        try:
 
            for inv_obj in inv_objs:
 
                inv_obj.cache_active = False
 
                log.debug('marking %s key for invalidation based on key=%s,repo_name=%s'
 
                  % (inv_obj, key, repo_name))
 
                invalidated_keys.append(inv_obj.cache_key)
 
                Session().add(inv_obj)
 
            Session().commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            Session().rollback()
 
        return invalidated_keys
 

	
 
    @classmethod
 
    def set_valid(cls, key):
 
        """
 
        Mark this cache key as active and currently cached
 

	
 
        :param key:
 
        """
 
        inv_obj = cls.get_by_key(key)
 
        inv_obj.cache_active = True
 
        Session().add(inv_obj)
 
        Session().commit()
 

	
 
    @classmethod
 
    def get_cache_map(cls):
 

	
 
        class cachemapdict(dict):
 

	
 
            def __init__(self, *args, **kwargs):
 
                fixkey = kwargs.get('fixkey')
 
                if fixkey:
 
                    del kwargs['fixkey']
 
                self.fixkey = fixkey
 
                super(cachemapdict, self).__init__(*args, **kwargs)
 

	
 
            def __getattr__(self, name):
 
                key = name
 
                if self.fixkey:
 
                    key, _prefix, _org_key = cls._get_key(key)
 
                if key in self.__dict__:
 
                    return self.__dict__[key]
 
                else:
 
                    return self[key]
 

	
 
            def __getitem__(self, key):
 
                if self.fixkey:
 
                    key, _prefix, _org_key = cls._get_key(key)
 
                try:
 
                    return super(cachemapdict, self).__getitem__(key)
 
                except KeyError:
 
                    return
 

	
 
        cache_map = cachemapdict(fixkey=True)
 
        for obj in cls.query().all():
 
            cache_map[obj.cache_key] = cachemapdict(obj.get_dict())
 
        return cache_map
 

	
 

	
 
class ChangesetComment(Base, BaseModel):
 
    __tablename__ = 'changeset_comments'
 
    __table_args__ = (
 
        Index('cc_revision_idx', 'revision'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
 
    repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    revision = Column('revision', String(40), nullable=True)
 
    pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
 
    line_no = Column('line_no', Unicode(10), nullable=True)
 
    hl_lines = Column('hl_lines', Unicode(512), nullable=True)
 
    f_path = Column('f_path', Unicode(1000), nullable=True)
 
    user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
 
    text = Column('text', UnicodeText(25000), nullable=False)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
    modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 

	
 
    author = relationship('User', lazy='joined')
 
    repo = relationship('Repository')
 
    status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
 
    pull_request = relationship('PullRequest', lazy='joined')
 

	
 
    @classmethod
 
    def get_users(cls, revision=None, pull_request_id=None):
 
        """
 
        Returns user associated with this ChangesetComment. ie those
 
        who actually commented
 

	
 
        :param cls:
 
        :param revision:
 
        """
 
        q = Session().query(User)\
 
                .join(ChangesetComment.author)
 
        if revision:
 
            q = q.filter(cls.revision == revision)
 
        elif pull_request_id:
 
            q = q.filter(cls.pull_request_id == pull_request_id)
 
        return q.all()
 

	
 

	
 
class ChangesetStatus(Base, BaseModel):
 
    __tablename__ = 'changeset_statuses'
 
    __table_args__ = (
 
        Index('cs_revision_idx', 'revision'),
 
        Index('cs_version_idx', 'version'),
 
        UniqueConstraint('repo_id', 'revision', 'version'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
 
    STATUS_APPROVED = 'approved'
 
    STATUS_REJECTED = 'rejected'
 
    STATUS_UNDER_REVIEW = 'under_review'
 

	
 
    STATUSES = [
 
        (STATUS_NOT_REVIEWED, _("Not Reviewed")),  # (no icon) and default
 
        (STATUS_APPROVED, _("Approved")),
 
        (STATUS_REJECTED, _("Rejected")),
 
        (STATUS_UNDER_REVIEW, _("Under Review")),
 
    ]
 

	
 
    changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
 
    repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
 
    revision = Column('revision', String(40), nullable=False)
 
    status = Column('status', String(128), nullable=False, default=DEFAULT)
 
    changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
 
    modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
 
    version = Column('version', Integer(), nullable=False, default=0)
 
    pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
 

	
 
    author = relationship('User', lazy='joined')
 
    repo = relationship('Repository')
 
    comment = relationship('ChangesetComment', lazy='joined')
 
    pull_request = relationship('PullRequest', lazy='joined')
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__,
 
            self.status, self.author
 
        )
 

	
 
    @classmethod
 
    def get_status_lbl(cls, value):
 
        return dict(cls.STATUSES).get(value)
 

	
 
    @property
 
    def status_lbl(self):
 
        return ChangesetStatus.get_status_lbl(self.status)
 

	
 

	
 
class PullRequest(Base, BaseModel):
 
    __tablename__ = 'pull_requests'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    STATUS_NEW = u'new'
 
    STATUS_OPEN = u'open'
 
    STATUS_CLOSED = u'closed'
 

	
 
    pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
 
    title = Column('title', Unicode(256), nullable=True)
 
    description = Column('description', UnicodeText(10240), nullable=True)
 
    status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
 
    _revisions = Column('revisions', UnicodeText(20500))  # 500 revisions max
 
    org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    org_ref = Column('org_ref', Unicode(256), nullable=False)
 
    other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    other_ref = Column('other_ref', Unicode(256), nullable=False)
 

	
 
    @hybrid_property
 
    def revisions(self):
 
        return self._revisions.split(':')
 

	
 
    @revisions.setter
 
    def revisions(self, val):
 
        self._revisions = ':'.join(val)
 

	
 
    @property
 
    def org_ref_parts(self):
 
        return self.org_ref.split(':')
 

	
 
    @property
 
    def other_ref_parts(self):
 
        return self.other_ref.split(':')
 

	
 
    author = relationship('User', lazy='joined')
 
    reviewers = relationship('PullRequestReviewers',
 
                             cascade="all, delete, delete-orphan")
 
    org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
 
    other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
 
    statuses = relationship('ChangesetStatus')
 
    comments = relationship('ChangesetComment',
 
                             cascade="all, delete, delete-orphan")
 

	
 
    def is_closed(self):
 
        return self.status == self.STATUS_CLOSED
 

	
 
    @property
 
    def last_review_status(self):
 
        return self.statuses[-1].status 
 
        return self.statuses[-1].status
 

	
 
    def __json__(self):
 
        return dict(
 
          revisions=self.revisions
 
        )
 

	
 

	
 
class PullRequestReviewers(Base, BaseModel):
 
    __tablename__ = 'pull_request_reviewers'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    def __init__(self, user=None, pull_request=None):
 
        self.user = user
 
        self.pull_request = pull_request
 

	
 
    pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
 
    pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
 

	
 
    user = relationship('User')
 
    pull_request = relationship('PullRequest')
 

	
 

	
 
class Notification(Base, BaseModel):
 
    __tablename__ = 'notifications'
 
    __table_args__ = (
 
        Index('notification_type_idx', 'type'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    TYPE_CHANGESET_COMMENT = u'cs_comment'
 
    TYPE_MESSAGE = u'message'
 
    TYPE_MENTION = u'mention'
 
    TYPE_REGISTRATION = u'registration'
 
    TYPE_PULL_REQUEST = u'pull_request'
 
    TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
 

	
 
    notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
 
    subject = Column('subject', Unicode(512), nullable=True)
 
    body = Column('body', UnicodeText(50000), nullable=True)
 
    created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
    type_ = Column('type', Unicode(256))
 

	
 
    created_by_user = relationship('User')
 
    notifications_to_users = relationship('UserNotification', lazy='joined',
 
                                          cascade="all, delete, delete-orphan")
 

	
 
    @property
 
    def recipients(self):
 
        return [x.user for x in UserNotification.query()\
 
                .filter(UserNotification.notification == self)\
 
                .order_by(UserNotification.user_id.asc()).all()]
 

	
 
    @classmethod
 
    def create(cls, created_by, subject, body, recipients, type_=None):
 
        if type_ is None:
 
            type_ = Notification.TYPE_MESSAGE
 

	
 
        notification = cls()
 
        notification.created_by_user = created_by
 
        notification.subject = subject
 
        notification.body = body
 
        notification.type_ = type_
 
        notification.created_on = datetime.datetime.now()
 

	
 
        for u in recipients:
 
            assoc = UserNotification()
 
            assoc.notification = notification
 
            u.notifications.append(assoc)
 
        Session().add(notification)
 
        return notification
 

	
 
    @property
 
    def description(self):
 
        from rhodecode.model.notification import NotificationModel
 
        return NotificationModel().make_description(self)
 

	
 

	
 
class UserNotification(Base, BaseModel):
 
    __tablename__ = 'user_to_notification'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'notification_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
 
    notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
 
    read = Column('read', Boolean, default=False)
 
    sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
 

	
 
    user = relationship('User', lazy="joined")
 
    notification = relationship('Notification', lazy="joined",
 
                                order_by=lambda: Notification.created_on.desc(),)
 

	
 
    def mark_as_read(self):
 
        self.read = True
 
        Session().add(self)
 

	
 

	
 
class DbMigrateVersion(Base, BaseModel):
 
    __tablename__ = 'db_migrate_version'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    repository_id = Column('repository_id', String(250), primary_key=True)
 
    repository_path = Column('repository_path', Text)
 
    version = Column('version', Integer)
rhodecode/public/css/pygments.css
Show inline comments
 
div.codeblock {
 
    overflow: auto;
 
    padding: 0px;
 
    border: 1px solid #ccc;
 
    background: #f8f8f8;
 
    font-size: 100%;
 
    line-height: 100%;
 
    /* new */
 
    line-height: 125%;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;     
 
    border-radius: 4px;
 
}
 
div.codeblock .code-header{
 
	border-bottom: 1px solid #CCCCCC;
 
	background: #EEEEEE;
 
	padding:10px 0 10px 0;
 
    border-bottom: 1px solid #CCCCCC;
 
    background: #EEEEEE;
 
    padding:10px 0 10px 0;
 
}
 

	
 
div.codeblock .code-header .stats{
 
	clear: both;
 
	padding: 6px 8px 6px 10px; 
 
	border-bottom: 1px solid rgb(204, 204, 204);  
 
	height: 23px;
 
	margin-bottom: 6px;
 
    clear: both;
 
    padding: 6px 8px 6px 10px;
 
    border-bottom: 1px solid rgb(204, 204, 204);
 
    height: 23px;
 
    margin-bottom: 6px;
 
}
 

	
 
div.codeblock .code-header .stats .left{
 
	float:left;
 
    float:left;
 
}
 
div.codeblock .code-header .stats .left.img{
 
	margin-top:-2px;
 
    margin-top:-2px;
 
}
 
div.codeblock .code-header .stats .left.item{
 
	float:left;
 
	padding: 0 9px 0 9px;
 
	border-right:1px solid #ccc;
 
    float:left;
 
    padding: 0 9px 0 9px;
 
    border-right:1px solid #ccc;
 
}
 
div.codeblock .code-header .stats .left.item pre{
 
	
 
}
 
div.codeblock .code-header .stats .left.item.last{
 
	border-right:none;
 
    border-right:none;
 
}
 
div.codeblock .code-header .stats .buttons{
 
	float:right;
 
	padding-right:4px;
 
    float:right;
 
    padding-right:4px;
 
}
 

	
 
div.codeblock .code-header .author{
 
	margin-left:25px;
 
	font-weight: bold;
 
	height: 25px;
 
    margin-left:25px;
 
    font-weight: bold;
 
    height: 25px;
 
}
 
div.codeblock .code-header .author .user{
 
	padding-top:3px;
 
    padding-top:3px;
 
}
 
div.codeblock .code-header .commit{
 
	margin-left:25px;
 
	font-weight: normal;
 
	white-space:pre;
 
    margin-left:25px;
 
    font-weight: normal;
 
    white-space:pre;
 
}
 

	
 
div.codeblock .code-body table{
 
    width: 0 !important;
 
    border: 0px !important;
 
}
 
div.codeblock .code-body table td {
 
	border: 0px !important;
 
    border: 0px !important;
 
}
 
div.code-body {
 
	background-color: #FFFFFF;
 
    background-color: #FFFFFF;
 
}
 

	
 
div.codeblock .code-header .search-path {
 
	padding: 0px 0px 0px 10px;
 
    padding: 0px 0px 0px 10px;
 
}
 

	
 
div.search-code-body {
 
    background-color: #FFFFFF;
 
    padding: 5px 0px 5px 10px;
 
}
 

	
 
div.search-code-body pre .match{
 
	background-color: #FAFFA6;
 
    background-color: #FAFFA6;
 
}
 
div.search-code-body pre .break{
 
	background-color: #DDE7EF;
 
	width: 100%;
 
	color: #747474;
 
	display: block;
 
	
 
    background-color: #DDE7EF;
 
    width: 100%;
 
    color: #747474;
 
    display: block;
 
}
 
div.annotatediv{
 
	margin-left:2px;
 
	margin-right:4px;
 
    margin-left:2px;
 
    margin-right:4px;
 
}
 
.code-highlight {
 
    padding: 0px;
 
    margin-top: 5px;
 
    margin-bottom: 5px;
 
    border-left: 2px solid #ccc;
 
}
 
.code-highlight pre, .linenodiv pre { 
 
	padding: 5px;
 
.code-highlight pre, .linenodiv pre {
 
    padding: 5px;
 
    margin: 0;
 
}
 
.code-highlight pre div:target { 
 
.code-highlight pre div:target {
 
    background-color: #FFFFBE !important;
 
}
 
    
 

	
 
.linenos a { text-decoration: none; }
 

	
 
.code { display: block; }
 
.code-highlight .hll, .codehilite .hll { background-color: #ffffcc }
 
.code-highlight .c, .codehilite .c { color: #408080; font-style: italic } /* Comment */
 
.code-highlight .err, .codehilite .err { border: 1px solid #FF0000 } /* Error */
 
.code-highlight .k, .codehilite .k { color: #008000; font-weight: bold } /* Keyword */
 
.code-highlight .o, .codehilite .o { color: #666666 } /* Operator */
 
.code-highlight .cm, .codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
 
.code-highlight .cp, .codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
 
.code-highlight .c1, .codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
 
.code-highlight .cs, .codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
 
.code-highlight .gd, .codehilite .gd { color: #A00000 } /* Generic.Deleted */
 
.code-highlight .ge, .codehilite .ge { font-style: italic } /* Generic.Emph */
 
.code-highlight .gr, .codehilite .gr { color: #FF0000 } /* Generic.Error */
 
.code-highlight .gh, .codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
 
.code-highlight .gi, .codehilite .gi { color: #00A000 } /* Generic.Inserted */
 
.code-highlight .go, .codehilite .go { color: #808080 } /* Generic.Output */
 
.code-highlight .gp, .codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
 
.code-highlight .gs, .codehilite .gs { font-weight: bold } /* Generic.Strong */
 
.code-highlight .gu, .codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
 
.code-highlight .gt, .codehilite .gt { color: #0040D0 } /* Generic.Traceback */
 
.code-highlight .kc, .codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
 
.code-highlight .kd, .codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
 
.code-highlight .kn, .codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
 
.code-highlight .kp, .codehilite .kp { color: #008000 } /* Keyword.Pseudo */
 
.code-highlight .kr, .codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
 
.code-highlight .kt, .codehilite .kt { color: #B00040 } /* Keyword.Type */
 
.code-highlight .m, .codehilite .m { color: #666666 } /* Literal.Number */
 
.code-highlight .s, .codehilite .s { color: #BA2121 } /* Literal.String */
 
.code-highlight .na, .codehilite .na { color: #7D9029 } /* Name.Attribute */
 
.code-highlight .nb, .codehilite .nb { color: #008000 } /* Name.Builtin */
 
.code-highlight .nc, .codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
 
.code-highlight .no, .codehilite .no { color: #880000 } /* Name.Constant */
 
.code-highlight .nd, .codehilite .nd { color: #AA22FF } /* Name.Decorator */
 
.code-highlight .ni, .codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
 
.code-highlight .ne, .codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
 
.code-highlight .nf, .codehilite .nf { color: #0000FF } /* Name.Function */
 
.code-highlight .nl, .codehilite .nl { color: #A0A000 } /* Name.Label */
 
.code-highlight .nn, .codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
 
.code-highlight .nt, .codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
 
.code-highlight .nv, .codehilite .nv { color: #19177C } /* Name.Variable */
 
.code-highlight .ow, .codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
 
.code-highlight .w, .codehilite .w { color: #bbbbbb } /* Text.Whitespace */
 
.code-highlight .mf, .codehilite .mf { color: #666666 } /* Literal.Number.Float */
 
.code-highlight .mh, .codehilite .mh { color: #666666 } /* Literal.Number.Hex */
 
.code-highlight .mi, .codehilite .mi { color: #666666 } /* Literal.Number.Integer */
 
.code-highlight .mo, .codehilite .mo { color: #666666 } /* Literal.Number.Oct */
 
.code-highlight .sb, .codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
 
.code-highlight .sc, .codehilite .sc { color: #BA2121 } /* Literal.String.Char */
 
.code-highlight .sd, .codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
 
.code-highlight .s2, .codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
 
.code-highlight .se, .codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
 
.code-highlight .sh, .codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
 
.code-highlight .si, .codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
 
.code-highlight .sx, .codehilite .sx { color: #008000 } /* Literal.String.Other */
 
.code-highlight .sr, .codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
 
.code-highlight .s1, .codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
 
.code-highlight .ss, .codehilite .ss { color: #19177C } /* Literal.String.Symbol */
 
.code-highlight .bp, .codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
 
.code-highlight .vc, .codehilite .vc { color: #19177C } /* Name.Variable.Class */
 
.code-highlight .vg, .codehilite .vg { color: #19177C } /* Name.Variable.Global */
 
.code-highlight .vi, .codehilite .vi { color: #19177C } /* Name.Variable.Instance */
 
.code-highlight .il, .codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
rhodecode/public/css/style.css
Show inline comments
 
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td
 
	{
 
	border: 0;
 
	outline: 0;
 
	font-size: 100%;
 
	vertical-align: baseline;
 
	background: transparent;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    border: 0;
 
    outline: 0;
 
    font-size: 100%;
 
    vertical-align: baseline;
 
    background: transparent;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
body {
 
	line-height: 1;
 
	height: 100%;
 
	background: url("../images/background.png") repeat scroll 0 0 #B0B0B0;
 
	font-family: Lucida Grande, Verdana, Lucida Sans Regular,
 
		Lucida Sans Unicode, Arial, sans-serif; font-size : 12px;
 
	color: #000;
 
	margin: 0;
 
	padding: 0;
 
	font-size: 12px;
 
    line-height: 1;
 
    height: 100%;
 
    background: url("../images/background.png") repeat scroll 0 0 #B0B0B0;
 
    font-family: Lucida Grande, Verdana, Lucida Sans Regular,
 
        Lucida Sans Unicode, Arial, sans-serif; font-size : 12px;
 
    color: #000;
 
    margin: 0;
 
    padding: 0;
 
    font-size: 12px;
 
}
 

	
 
ol,ul {
 
	list-style: none;
 
    list-style: none;
 
}
 

	
 
blockquote,q {
 
	quotes: none;
 
    quotes: none;
 
}
 

	
 
blockquote:before,blockquote:after,q:before,q:after {
 
	content: none;
 
    content: none;
 
}
 

	
 
:focus {
 
	outline: 0;
 
    outline: 0;
 
}
 

	
 
del {
 
	text-decoration: line-through;
 
    text-decoration: line-through;
 
}
 

	
 
table {
 
	border-collapse: collapse;
 
	border-spacing: 0;
 
    border-collapse: collapse;
 
    border-spacing: 0;
 
}
 

	
 
html {
 
	height: 100%;
 
    height: 100%;
 
}
 

	
 
a {
 
	color: #003367;
 
	text-decoration: none;
 
	cursor: pointer;
 
    color: #003367;
 
    text-decoration: none;
 
    cursor: pointer;
 
}
 

	
 
a:hover {
 
	color: #316293;
 
	text-decoration: underline;
 
    color: #316293;
 
    text-decoration: underline;
 
}
 

	
 
h1,h2,h3,h4,h5,h6,
 
div.h1,div.h2,div.h3,div.h4,div.h5,div.h6 {
 
	color: #292929;
 
	font-weight: 700;
 
    color: #292929;
 
    font-weight: 700;
 
}
 

	
 
h1,div.h1 {
 
	font-size: 22px;
 
    font-size: 22px;
 
}
 

	
 
h2,div.h2 {
 
	font-size: 20px;
 
    font-size: 20px;
 
}
 

	
 
h3,div.h3 {
 
	font-size: 18px;
 
    font-size: 18px;
 
}
 

	
 
h4,div.h4 {
 
	font-size: 16px;
 
    font-size: 16px;
 
}
 

	
 
h5,div.h5 {
 
	font-size: 14px;
 
    font-size: 14px;
 
}
 

	
 
h6,div.h6 {
 
	font-size: 11px;
 
    font-size: 11px;
 
}
 

	
 
ul.circle {
 
	list-style-type: circle;
 
    list-style-type: circle;
 
}
 

	
 
ul.disc {
 
	list-style-type: disc;
 
    list-style-type: disc;
 
}
 

	
 
ul.square {
 
	list-style-type: square;
 
    list-style-type: square;
 
}
 

	
 
ol.lower-roman {
 
	list-style-type: lower-roman;
 
    list-style-type: lower-roman;
 
}
 

	
 
ol.upper-roman {
 
	list-style-type: upper-roman;
 
    list-style-type: upper-roman;
 
}
 

	
 
ol.lower-alpha {
 
	list-style-type: lower-alpha;
 
    list-style-type: lower-alpha;
 
}
 

	
 
ol.upper-alpha {
 
	list-style-type: upper-alpha;
 
    list-style-type: upper-alpha;
 
}
 

	
 
ol.decimal {
 
	list-style-type: decimal;
 
    list-style-type: decimal;
 
}
 

	
 
div.color {
 
	clear: both;
 
	overflow: hidden;
 
	position: absolute;
 
	background: #FFF;
 
	margin: 7px 0 0 60px;
 
	padding: 1px 1px 1px 0;
 
    clear: both;
 
    overflow: hidden;
 
    position: absolute;
 
    background: #FFF;
 
    margin: 7px 0 0 60px;
 
    padding: 1px 1px 1px 0;
 
}
 

	
 
div.color a {
 
	width: 15px;
 
	height: 15px;
 
	display: block;
 
	float: left;
 
	margin: 0 0 0 1px;
 
	padding: 0;
 
    width: 15px;
 
    height: 15px;
 
    display: block;
 
    float: left;
 
    margin: 0 0 0 1px;
 
    padding: 0;
 
}
 

	
 
div.options {
 
	clear: both;
 
	overflow: hidden;
 
	position: absolute;
 
	background: #FFF;
 
	margin: 7px 0 0 162px;
 
	padding: 0;
 
    clear: both;
 
    overflow: hidden;
 
    position: absolute;
 
    background: #FFF;
 
    margin: 7px 0 0 162px;
 
    padding: 0;
 
}
 

	
 
div.options a {
 
	height: 1%;
 
	display: block;
 
	text-decoration: none;
 
	margin: 0;
 
	padding: 3px 8px;
 
    height: 1%;
 
    display: block;
 
    text-decoration: none;
 
    margin: 0;
 
    padding: 3px 8px;
 
}
 

	
 
.top-left-rounded-corner {
 
	-webkit-border-top-left-radius: 8px;
 
	-khtml-border-radius-topleft: 8px;
 
	-moz-border-radius-topleft: 8px;
 
	border-top-left-radius: 8px;
 
    -webkit-border-top-left-radius: 8px;
 
    -khtml-border-radius-topleft: 8px;
 
    -moz-border-radius-topleft: 8px;
 
    border-top-left-radius: 8px;
 
}
 

	
 
.top-right-rounded-corner {
 
	-webkit-border-top-right-radius: 8px;
 
	-khtml-border-radius-topright: 8px;
 
	-moz-border-radius-topright: 8px;
 
	border-top-right-radius: 8px;
 
    -webkit-border-top-right-radius: 8px;
 
    -khtml-border-radius-topright: 8px;
 
    -moz-border-radius-topright: 8px;
 
    border-top-right-radius: 8px;
 
}
 

	
 
.bottom-left-rounded-corner {
 
	-webkit-border-bottom-left-radius: 8px;
 
	-khtml-border-radius-bottomleft: 8px;
 
	-moz-border-radius-bottomleft: 8px;
 
	border-bottom-left-radius: 8px;
 
    -webkit-border-bottom-left-radius: 8px;
 
    -khtml-border-radius-bottomleft: 8px;
 
    -moz-border-radius-bottomleft: 8px;
 
    border-bottom-left-radius: 8px;
 
}
 

	
 
.bottom-right-rounded-corner {
 
	-webkit-border-bottom-right-radius: 8px;
 
	-khtml-border-radius-bottomright: 8px;
 
	-moz-border-radius-bottomright: 8px;
 
	border-bottom-right-radius: 8px;
 
    -webkit-border-bottom-right-radius: 8px;
 
    -khtml-border-radius-bottomright: 8px;
 
    -moz-border-radius-bottomright: 8px;
 
    border-bottom-right-radius: 8px;
 
}
 

	
 
.top-left-rounded-corner-mid {
 
    -webkit-border-top-left-radius: 4px;
 
    -khtml-border-radius-topleft: 4px;
 
    -moz-border-radius-topleft: 4px;
 
    border-top-left-radius: 4px;
 
}
 

	
 
.top-right-rounded-corner-mid {
 
    -webkit-border-top-right-radius: 4px;
 
    -khtml-border-radius-topright: 4px;
 
    -moz-border-radius-topright: 4px;
 
    border-top-right-radius: 4px;
 
}
 

	
 
.bottom-left-rounded-corner-mid {
 
    -webkit-border-bottom-left-radius: 4px;
 
    -khtml-border-radius-bottomleft: 4px;
 
    -moz-border-radius-bottomleft: 4px;
 
    border-bottom-left-radius: 4px;
 
}
 

	
 
.bottom-right-rounded-corner-mid {
 
    -webkit-border-bottom-right-radius: 4px;
 
    -khtml-border-radius-bottomright: 4px;
 
    -moz-border-radius-bottomright: 4px;
 
    border-bottom-right-radius: 4px;
 
}
 

	
 
.help-block {
 
    color: #999999;
 
    display: block;
 
    margin-bottom: 0;
 
    margin-top: 5px;
 
}
 

	
 
.empty_data{
 
    color:#B9B9B9;	
 
    color:#B9B9B9;
 
}
 

	
 
a.permalink{
 
	visibility: hidden;
 
    visibility: hidden;
 
}
 

	
 
a.permalink:hover{
 
	text-decoration: none;
 
    text-decoration: none;
 
}
 

	
 
h1:hover > a.permalink,
 
h2:hover > a.permalink,
 
h3:hover > a.permalink,
 
h4:hover > a.permalink,
 
h5:hover > a.permalink,
 
h6:hover > a.permalink,
 
div:hover > a.permalink {
 
    visibility: visible;
 
}
 

	
 
#header {
 
	margin: 0;
 
	padding: 0 10px;
 
    margin: 0;
 
    padding: 0 10px;
 
}
 

	
 
#header ul#logged-user {
 
	margin-bottom: 5px !important;
 
	-webkit-border-radius: 0px 0px 8px 8px;
 
	-khtml-border-radius: 0px 0px 8px 8px;
 
	-moz-border-radius: 0px 0px 8px 8px;
 
	border-radius: 0px 0px 8px 8px;
 
	height: 37px;
 
    background-color: #003B76;    
 
    margin-bottom: 5px !important;
 
    -webkit-border-radius: 0px 0px 8px 8px;
 
    -khtml-border-radius: 0px 0px 8px 8px;
 
    -moz-border-radius: 0px 0px 8px 8px;
 
    border-radius: 0px 0px 8px 8px;
 
    height: 37px;
 
    background-color: #003B76;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
 
    background-image: -moz-linear-gradient(top, #003b76, #00376e);
 
    background-image: -ms-linear-gradient(top, #003b76, #00376e);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
 
    background-image: -webkit-linear-gradient(top, #003b76, #00376e);
 
    background-image: -o-linear-gradient(top, #003b76, #00376e);
 
    background-image: linear-gradient(top, #003b76, #00376e);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
 
	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
}
 

	
 
#header ul#logged-user li {
 
	list-style: none;
 
	float: left;
 
	margin: 8px 0 0;
 
	padding: 4px 12px;
 
	border-left: 1px solid #316293;
 
    list-style: none;
 
    float: left;
 
    margin: 8px 0 0;
 
    padding: 4px 12px;
 
    border-left: 1px solid #316293;
 
}
 

	
 
#header ul#logged-user li.first {
 
	border-left: none;
 
	margin: 4px;
 
    border-left: none;
 
    margin: 4px;
 
}
 

	
 
#header ul#logged-user li.first div.gravatar {
 
	margin-top: -2px;
 
    margin-top: -2px;
 
}
 

	
 
#header ul#logged-user li.first div.account {
 
	padding-top: 4px;
 
	float: left;
 
    padding-top: 4px;
 
    float: left;
 
}
 

	
 
#header ul#logged-user li.last {
 
	border-right: none;
 
    border-right: none;
 
}
 

	
 
#header ul#logged-user li a {
 
	color: #fff;
 
	font-weight: 700;
 
	text-decoration: none;
 
    color: #fff;
 
    font-weight: 700;
 
    text-decoration: none;
 
}
 

	
 
#header ul#logged-user li a:hover {
 
	text-decoration: underline;
 
    text-decoration: underline;
 
}
 

	
 
#header ul#logged-user li.highlight a {
 
	color: #fff;
 
    color: #fff;
 
}
 

	
 
#header ul#logged-user li.highlight a:hover {
 
	color: #FFF;
 
    color: #FFF;
 
}
 

	
 
#header #header-inner {
 
	min-height: 44px;
 
	clear: both;
 
	position: relative;
 
    min-height: 44px;
 
    clear: both;
 
    position: relative;
 
    background-color: #003B76;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
 
    background-image: -moz-linear-gradient(top, #003b76, #00376e);
 
    background-image: -ms-linear-gradient(top, #003b76, #00376e);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) );
 
    background-image: -webkit-linear-gradient(top, #003b76, #00376e);
 
    background-image: -o-linear-gradient(top, #003b76, #00376e);
 
    background-image: linear-gradient(top, #003b76, #00376e);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
 
	margin: 0;
 
	padding: 0;
 
	display: block;
 
	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
	-webkit-border-radius: 4px 4px 4px 4px;
 
	-khtml-border-radius: 4px 4px 4px 4px;
 
	-moz-border-radius: 4px 4px 4px 4px;
 
	border-radius: 4px 4px 4px 4px;
 
    margin: 0;
 
    padding: 0;
 
    display: block;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    -webkit-border-radius: 4px 4px 4px 4px;
 
    -khtml-border-radius: 4px 4px 4px 4px;
 
    -moz-border-radius: 4px 4px 4px 4px;
 
    border-radius: 4px 4px 4px 4px;
 
}
 
#header #header-inner.hover{
 
	position: fixed !important;
 
	width: 100% !important;
 
	margin-left: -10px !important;
 
	z-index: 10000;
 
    position: fixed !important;
 
    width: 100% !important;
 
    margin-left: -10px !important;
 
    z-index: 10000;
 
    -webkit-border-radius: 0px 0px 0px 0px;
 
    -khtml-border-radius: 0px 0px 0px 0px;
 
    -moz-border-radius: 0px 0px 0px 0px;
 
    border-radius: 0px 0px 0px 0px;	
 
    border-radius: 0px 0px 0px 0px;
 
}
 

	
 
.ie7 #header #header-inner.hover,
 
.ie8 #header #header-inner.hover,
 
.ie9 #header #header-inner.hover
 
{
 
    z-index: auto !important;
 
}
 

	
 
.header-pos-fix, .anchor{
 
	margin-top: -46px;
 
	padding-top: 46px;
 
    margin-top: -46px;
 
    padding-top: 46px;
 
}
 

	
 
#header #header-inner #home a {
 
	height: 40px;
 
	width: 46px;
 
	display: block;
 
	background: url("../images/button_home.png");
 
	background-position: 0 0;
 
	margin: 0;
 
	padding: 0;
 
    height: 40px;
 
    width: 46px;
 
    display: block;
 
    background: url("../images/button_home.png");
 
    background-position: 0 0;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#header #header-inner #home a:hover {
 
	background-position: 0 -40px;
 
    background-position: 0 -40px;
 
}
 

	
 
#header #header-inner #logo {
 
	float: left;
 
	position: absolute;
 
    float: left;
 
    position: absolute;
 
}
 

	
 
#header #header-inner #logo h1 {
 
	color: #FFF;
 
	font-size: 20px;
 
	margin: 12px 0 0 13px;
 
	padding: 0;
 
    color: #FFF;
 
    font-size: 20px;
 
    margin: 12px 0 0 13px;
 
    padding: 0;
 
}
 

	
 
#header #header-inner #logo a {
 
	color: #fff;
 
	text-decoration: none;
 
    color: #fff;
 
    text-decoration: none;
 
}
 

	
 
#header #header-inner #logo a:hover {
 
	color: #bfe3ff;
 
    color: #bfe3ff;
 
}
 

	
 
#header #header-inner #quick,#header #header-inner #quick ul {
 
	position: relative;
 
	float: right;
 
	list-style-type: none;
 
	list-style-position: outside;
 
	margin: 8px 8px 0 0;
 
	padding: 0;
 
    position: relative;
 
    float: right;
 
    list-style-type: none;
 
    list-style-position: outside;
 
    margin: 8px 8px 0 0;
 
    padding: 0;
 
}
 

	
 
#header #header-inner #quick li {
 
	position: relative;
 
	float: left;
 
	margin: 0 5px 0 0;
 
	padding: 0;
 
    position: relative;
 
    float: left;
 
    margin: 0 5px 0 0;
 
    padding: 0;
 
}
 

	
 
#header #header-inner #quick li a.menu_link {
 
	top: 0;
 
	left: 0;
 
	height: 1%;
 
	display: block;
 
	clear: both;
 
	overflow: hidden;
 
	color: #FFF;
 
	font-weight: 700;
 
	text-decoration: none;
 
	background: #369;
 
	padding: 0;
 
	-webkit-border-radius: 4px 4px 4px 4px;
 
	-khtml-border-radius: 4px 4px 4px 4px;
 
	-moz-border-radius: 4px 4px 4px 4px;
 
	border-radius: 4px 4px 4px 4px;
 
    top: 0;
 
    left: 0;
 
    height: 1%;
 
    display: block;
 
    clear: both;
 
    overflow: hidden;
 
    color: #FFF;
 
    font-weight: 700;
 
    text-decoration: none;
 
    background: #369;
 
    padding: 0;
 
    -webkit-border-radius: 4px 4px 4px 4px;
 
    -khtml-border-radius: 4px 4px 4px 4px;
 
    -moz-border-radius: 4px 4px 4px 4px;
 
    border-radius: 4px 4px 4px 4px;
 
}
 

	
 
#header #header-inner #quick li span.short {
 
	padding: 9px 6px 8px 6px;
 
    padding: 9px 6px 8px 6px;
 
}
 

	
 
#header #header-inner #quick li span {
 
	top: 0;
 
	right: 0;
 
	height: 1%;
 
	display: block;
 
	float: left;
 
	border-left: 1px solid #3f6f9f;
 
	margin: 0;
 
	padding: 10px 12px 8px 10px;
 
    top: 0;
 
    right: 0;
 
    height: 1%;
 
    display: block;
 
    float: left;
 
    border-left: 1px solid #3f6f9f;
 
    margin: 0;
 
    padding: 10px 12px 8px 10px;
 
}
 

	
 
#header #header-inner #quick li span.normal {
 
	border: none;
 
	padding: 10px 12px 8px;
 
    border: none;
 
    padding: 10px 12px 8px;
 
}
 

	
 
#header #header-inner #quick li span.icon {
 
	top: 0;
 
	left: 0;
 
	border-left: none;
 
	border-right: 1px solid #2e5c89;
 
	padding: 8px 6px 4px;
 
	min-width: 16px;
 
	min-height: 16px;
 
    top: 0;
 
    left: 0;
 
    border-left: none;
 
    border-right: 1px solid #2e5c89;
 
    padding: 8px 6px 4px;
 
    min-width: 16px;
 
    min-height: 16px;
 
}
 

	
 
#header #header-inner #quick li span.icon_short {
 
	top: 0;
 
	left: 0;
 
	border-left: none;
 
	border-right: 1px solid #2e5c89;
 
	padding: 8px 6px 4px;
 
    top: 0;
 
    left: 0;
 
    border-left: none;
 
    border-right: 1px solid #2e5c89;
 
    padding: 8px 6px 4px;
 
}
 

	
 
#header #header-inner #quick li span.icon img,#header #header-inner #quick li span.icon_short img
 
	{
 
	margin: 0px -2px 0px 0px;
 
    {
 
    margin: 0px -2px 0px 0px;
 
}
 

	
 
#header #header-inner #quick li.current a,
 
#header #header-inner #quick li a:hover {
 
	background: #4e4e4e no-repeat top left;
 
    background: #4e4e4e no-repeat top left;
 
}
 

	
 
#header #header-inner #quick li.current a span,
 
#header #header-inner #quick li a:hover span {
 
	border-left: 1px solid #545454;
 
    border-left: 1px solid #545454;
 
}
 

	
 
#header #header-inner #quick li.current a span.icon,
 
#header #header-inner #quick li.current a span.icon_short,
 
#header #header-inner #quick li a:hover span.icon,
 
#header #header-inner #quick li a:hover span.icon_short
 
	{
 
	border-left: none;
 
	border-right: 1px solid #464646;
 
    {
 
    border-left: none;
 
    border-right: 1px solid #464646;
 
}
 

	
 
#header #header-inner #quick ul {
 
	top: 29px;
 
	right: 0;
 
	min-width: 200px;
 
	display: none;
 
	position: absolute;
 
	background: #FFF;
 
	border: 1px solid #666;
 
	border-top: 1px solid #003367;
 
	z-index: 100;
 
	margin: 0px 0px 0px 0px;
 
	padding: 0;
 
    top: 29px;
 
    right: 0;
 
    min-width: 200px;
 
    display: none;
 
    position: absolute;
 
    background: #FFF;
 
    border: 1px solid #666;
 
    border-top: 1px solid #003367;
 
    z-index: 100;
 
    margin: 0px 0px 0px 0px;
 
    padding: 0;
 
}
 

	
 
#header #header-inner #quick ul.repo_switcher {
 
	max-height: 275px;
 
	overflow-x: hidden;
 
	overflow-y: auto;
 
    max-height: 275px;
 
    overflow-x: hidden;
 
    overflow-y: auto;
 
}
 

	
 
#header #header-inner #quick ul.repo_switcher li.qfilter_rs {
 
	float: none;
 
	margin: 0;
 
	border-bottom: 2px solid #003367;
 
    float: none;
 
    margin: 0;
 
    border-bottom: 2px solid #003367;
 
}
 

	
 
#header #header-inner #quick .repo_switcher_type {
 
	position: absolute;
 
	left: 0;
 
	top: 9px;
 
    position: absolute;
 
    left: 0;
 
    top: 9px;
 
}
 

	
 
#header #header-inner #quick li ul li {
 
	border-bottom: 1px solid #ddd;
 
    border-bottom: 1px solid #ddd;
 
}
 

	
 
#header #header-inner #quick li ul li a {
 
	width: 182px;
 
	height: auto;
 
	display: block;
 
	float: left;
 
	background: #FFF;
 
	color: #003367;
 
	font-weight: 400;
 
	margin: 0;
 
	padding: 7px 9px;
 
    width: 182px;
 
    height: auto;
 
    display: block;
 
    float: left;
 
    background: #FFF;
 
    color: #003367;
 
    font-weight: 400;
 
    margin: 0;
 
    padding: 7px 9px;
 
}
 

	
 
#header #header-inner #quick li ul li a:hover {
 
	color: #000;
 
	background: #FFF;
 
    color: #000;
 
    background: #FFF;
 
}
 

	
 
#header #header-inner #quick ul ul {
 
	top: auto;
 
    top: auto;
 
}
 

	
 
#header #header-inner #quick li ul ul {
 
	right: 200px;
 
	max-height: 290px;
 
	overflow: auto;
 
	overflow-x: hidden;
 
	white-space: normal;
 
    right: 200px;
 
    max-height: 290px;
 
    overflow: auto;
 
    overflow-x: hidden;
 
    white-space: normal;
 
}
 

	
 
#header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover
 
	{
 
	background: url("../images/icons/book.png") no-repeat scroll 4px 9px
 
		#FFF;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/book.png") no-repeat scroll 4px 9px
 
        #FFF;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover
 
	{
 
	background: url("../images/icons/lock.png") no-repeat scroll 4px 9px
 
		#FFF;
 
	min-width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/lock.png") no-repeat scroll 4px 9px
 
        #FFF;
 
    min-width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover
 
	{
 
	background: url("../images/icons/lock_open.png") no-repeat scroll 4px
 
		9px #FFF;
 
	min-width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/lock_open.png") no-repeat scroll 4px
 
        9px #FFF;
 
    min-width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover
 
	{
 
	background: url("../images/icons/hgicon.png") no-repeat scroll 4px 9px
 
		#FFF;
 
	min-width: 167px;
 
	margin: 0 0 0 14px;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/hgicon.png") no-repeat scroll 4px 9px
 
        #FFF;
 
    min-width: 167px;
 
    margin: 0 0 0 14px;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover
 
	{
 
	background: url("../images/icons/giticon.png") no-repeat scroll 4px 9px
 
		#FFF;
 
	min-width: 167px;
 
	margin: 0 0 0 14px;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/giticon.png") no-repeat scroll 4px 9px
 
        #FFF;
 
    min-width: 167px;
 
    margin: 0 0 0 14px;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover
 
	{
 
	background: url("../images/icons/database_edit.png") no-repeat scroll
 
		4px 9px #FFF;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/database_edit.png") no-repeat scroll
 
        4px 9px #FFF;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover
 
	{
 
	background: url("../images/icons/database_link.png") no-repeat scroll
 
		4px 9px #FFF;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: url("../images/icons/database_link.png") no-repeat scroll
 
        4px 9px #FFF;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover
 
	{
 
	background: #FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover
 
	{
 
	background: #FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.defaults,#header #header-inner #quick li ul li a.defaults:hover
 
    {
 
    background: #FFF url("../images/icons/wrench.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover
 
	{
 
	background: #FFF url("../images/icons/cog.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/cog.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover
 
	{
 
	background: #FFF url("../images/icons/key.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/key.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover
 
	{
 
	background: #FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover
 
	{
 
	background: #FFF url("../images/icons/arrow_divide.png") no-repeat 4px
 
		9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/arrow_divide.png") no-repeat 4px
 
        9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.locking_add,#header #header-inner #quick li ul li a.locking_add:hover
 
    {
 
    background: #FFF url("../images/icons/lock_add.png") no-repeat 4px
 
        9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.locking_del,#header #header-inner #quick li ul li a.locking_del:hover
 
    {
 
    background: #FFF url("../images/icons/lock_delete.png") no-repeat 4px
 
        9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.pull_request,#header #header-inner #quick li ul li a.pull_request:hover
 
    {
 
    background: #FFF url("../images/icons/arrow_join.png") no-repeat 4px
 
        9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.compare_request,#header #header-inner #quick li ul li a.compare_request:hover
 
    {
 
    background: #FFF url("../images/icons/arrow_inout.png") no-repeat 4px
 
        9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover
 
	{
 
	background: #FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover
 
	{
 
	background: #FFF url("../images/icons/delete.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/delete.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover
 
	{
 
	background: #FFF url("../images/icons/arrow_branch.png") no-repeat 4px
 
		9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    {
 
    background: #FFF url("../images/icons/arrow_branch.png") no-repeat 4px
 
        9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.tags,
 
#header #header-inner #quick li ul li a.tags:hover{
 
	background: #FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    background: #FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.bookmarks,
 
#header #header-inner #quick li ul li a.bookmarks:hover{
 
    background: #FFF url("../images/icons/tag_green.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
#header #header-inner #quick li ul li a.admin,
 
#header #header-inner #quick li ul li a.admin:hover{
 
	background: #FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
 
	width: 167px;
 
	margin: 0;
 
	padding: 12px 9px 7px 24px;
 
    background: #FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
 
    width: 167px;
 
    margin: 0;
 
    padding: 12px 9px 7px 24px;
 
}
 

	
 
.groups_breadcrumbs a {
 
	color: #fff;
 
    color: #fff;
 
}
 

	
 
.groups_breadcrumbs a:hover {
 
	color: #bfe3ff;
 
	text-decoration: none;
 
    color: #bfe3ff;
 
    text-decoration: none;
 
}
 

	
 
td.quick_repo_menu {
 
	background: #FFF url("../images/vertical-indicator.png") 8px 50% no-repeat !important;
 
	cursor: pointer;
 
	width: 8px;
 
	border: 1px solid transparent;
 
    background: #FFF url("../images/vertical-indicator.png") 8px 50% no-repeat !important;
 
    cursor: pointer;
 
    width: 8px;
 
    border: 1px solid transparent;
 
}
 

	
 
td.quick_repo_menu.active {
 
    background: url("../images/dt-arrow-dn.png") no-repeat scroll 5px 50% #FFFFFF !important;
 
    border: 1px solid #003367;
 
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
 
    cursor: pointer;
 
}
 

	
 
td.quick_repo_menu .menu_items {
 
	margin-top: 10px;
 
	margin-left:-6px;
 
	width: 150px;
 
	position: absolute;
 
	background-color: #FFF;
 
	background: none repeat scroll 0 0 #FFFFFF;
 
	border-color: #003367 #666666 #666666;
 
	border-right: 1px solid #666666;
 
	border-style: solid;
 
	border-width: 1px;
 
	box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
 
	border-top-style: none;
 
    margin-top: 10px;
 
    margin-left:-6px;
 
    width: 150px;
 
    position: absolute;
 
    background-color: #FFF;
 
    background: none repeat scroll 0 0 #FFFFFF;
 
    border-color: #003367 #666666 #666666;
 
    border-right: 1px solid #666666;
 
    border-style: solid;
 
    border-width: 1px;
 
    box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
 
    border-top-style: none;
 
}
 

	
 
td.quick_repo_menu .menu_items li {
 
	padding: 0 !important;
 
    padding: 0 !important;
 
}
 

	
 
td.quick_repo_menu .menu_items a {
 
	display: block;
 
	padding: 4px 12px 4px 8px;
 
    display: block;
 
    padding: 4px 12px 4px 8px;
 
}
 

	
 
td.quick_repo_menu .menu_items a:hover {
 
	background-color: #EEE;
 
	text-decoration: none;
 
    background-color: #EEE;
 
    text-decoration: none;
 
}
 

	
 
td.quick_repo_menu .menu_items .icon img {
 
	margin-bottom: -2px;
 
    margin-bottom: -2px;
 
}
 

	
 
td.quick_repo_menu .menu_items.hidden {
 
	display: none;
 
    display: none;
 
}
 

	
 
.yui-dt-first th {
 
	text-align: left;
 
    text-align: left;
 
}
 

	
 
/*
 
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
 
Code licensed under the BSD License:
 
http://developer.yahoo.com/yui/license.html
 
version: 2.9.0
 
*/
 
.yui-skin-sam .yui-dt-mask {
 
    position: absolute;
 
    z-index: 9500;
 
}
 
.yui-dt-tmp {
 
    position: absolute;
 
    left: -9000px;
 
}
 
.yui-dt-scrollable .yui-dt-bd { overflow: auto }
 
.yui-dt-scrollable .yui-dt-hd {
 
    overflow: hidden;
 
    position: relative;
 
}
 
.yui-dt-scrollable .yui-dt-bd thead tr,
 
.yui-dt-scrollable .yui-dt-bd thead th {
 
    position: absolute;
 
    left: -1500px;
 
}
 
.yui-dt-scrollable tbody { -moz-outline: 0 }
 
.yui-skin-sam thead .yui-dt-sortable { cursor: pointer }
 
.yui-skin-sam thead .yui-dt-draggable { cursor: move }
 
.yui-dt-coltarget {
 
    position: absolute;
 
    z-index: 999;
 
}
 
.yui-dt-hd { zoom: 1 }
 
th.yui-dt-resizeable .yui-dt-resizerliner { position: relative }
 
.yui-dt-resizer {
 
    position: absolute;
 
    right: 0;
 
    bottom: 0;
 
    height: 100%;
 
    cursor: e-resize;
 
    cursor: col-resize;
 
    background-color: #CCC;
 
    opacity: 0;
 
    filter: alpha(opacity=0);
 
}
 
.yui-dt-resizerproxy {
 
    visibility: hidden;
 
    position: absolute;
 
    z-index: 9000;
 
    background-color: #CCC;
 
    opacity: 0;
 
    filter: alpha(opacity=0);
 
}
 
th.yui-dt-hidden .yui-dt-liner,
 
td.yui-dt-hidden .yui-dt-liner,
 
th.yui-dt-hidden .yui-dt-resizer { display: none }
 
.yui-dt-editor,
 
.yui-dt-editor-shim {
 
    position: absolute;
 
    z-index: 9000;
 
}
 
.yui-skin-sam .yui-dt table {
 
    margin: 0;
 
    padding: 0;
 
    font-family: arial;
 
    font-size: inherit;
 
    border-collapse: separate;
 
    *border-collapse: collapse;
 
    border-spacing: 0;
 
    border: 1px solid #7f7f7f;
 
}
 
.yui-skin-sam .yui-dt thead { border-spacing: 0 }
 
.yui-skin-sam .yui-dt caption {
 
    color: #000;
 
    font-size: 85%;
 
    font-weight: normal;
 
    font-style: italic;
 
    line-height: 1;
 
    padding: 1em 0;
 
    text-align: center;
 
}
 
.yui-skin-sam .yui-dt th { background: #d8d8da url(../images/sprite.png) repeat-x 0 0 }
 
.yui-skin-sam .yui-dt th,
 
.yui-skin-sam .yui-dt th a {
 
    font-weight: normal;
 
    text-decoration: none;
 
    color: #000;
 
    vertical-align: bottom;
 
}
 
.yui-skin-sam .yui-dt th {
 
    margin: 0;
 
    padding: 0;
 
    border: 0;
 
    border-right: 1px solid #cbcbcb;
 
}
 
.yui-skin-sam .yui-dt tr.yui-dt-first td { border-top: 1px solid #7f7f7f }
 
.yui-skin-sam .yui-dt th .yui-dt-liner { white-space: nowrap }
 
.yui-skin-sam .yui-dt-liner {
 
    margin: 0;
 
    padding: 0;
 
}
 
.yui-skin-sam .yui-dt-coltarget {
 
    width: 5px;
 
    background-color: red;
 
}
 
.yui-skin-sam .yui-dt td {
 
    margin: 0;
 
    padding: 0;
 
    border: 0;
 
    border-right: 1px solid #cbcbcb;
 
    text-align: left;
 
}
 
.yui-skin-sam .yui-dt-list td { border-right: 0 }
 
.yui-skin-sam .yui-dt-resizer { width: 6px }
 
.yui-skin-sam .yui-dt-mask {
 
    background-color: #000;
 
    opacity: .25;
 
    filter: alpha(opacity=25);
 
}
 
.yui-skin-sam .yui-dt-message { background-color: #FFF }
 
.yui-skin-sam .yui-dt-scrollable table { border: 0 }
 
.yui-skin-sam .yui-dt-scrollable .yui-dt-hd {
 
    border-left: 1px solid #7f7f7f;
 
    border-top: 1px solid #7f7f7f;
 
    border-right: 1px solid #7f7f7f;
 
}
 
.yui-skin-sam .yui-dt-scrollable .yui-dt-bd {
 
    border-left: 1px solid #7f7f7f;
 
    border-bottom: 1px solid #7f7f7f;
 
    border-right: 1px solid #7f7f7f;
 
    background-color: #FFF;
 
}
 
.yui-skin-sam .yui-dt-scrollable .yui-dt-data tr.yui-dt-last td { border-bottom: 1px solid #7f7f7f }
 
.yui-skin-sam th.yui-dt-asc,
 
.yui-skin-sam th.yui-dt-desc { background: url(../images/sprite.png) repeat-x 0 -100px }
 
.yui-skin-sam th.yui-dt-sortable .yui-dt-label { margin-right: 10px }
 
.yui-skin-sam th.yui-dt-asc .yui-dt-liner { background: url(../images/dt-arrow-up.png) no-repeat right }
 
.yui-skin-sam th.yui-dt-desc .yui-dt-liner { background: url(../images/dt-arrow-dn.png) no-repeat right }
 
tbody .yui-dt-editable { cursor: pointer }
 
.yui-dt-editor {
 
    text-align: left;
 
    background-color: #f2f2f2;
 
    border: 1px solid #808080;
 
    padding: 6px;
 
}
 
.yui-dt-editor label {
 
    padding-left: 4px;
 
    padding-right: 6px;
 
}
 
.yui-dt-editor .yui-dt-button {
 
    padding-top: 6px;
 
    text-align: right;
 
}
 
.yui-dt-editor .yui-dt-button button {
 
    background: url(../images/sprite.png) repeat-x 0 0;
 
    border: 1px solid #999;
 
    width: 4em;
 
    height: 1.8em;
 
    margin-left: 6px;
 
}
 
.yui-dt-editor .yui-dt-button button.yui-dt-default {
 
    background: url(../images/sprite.png) repeat-x 0 -1400px;
 
    background-color: #5584e0;
 
    border: 1px solid #304369;
 
    color: #FFF;
 
}
 
.yui-dt-editor .yui-dt-button button:hover {
 
    background: url(../images/sprite.png) repeat-x 0 -1300px;
 
    color: #000;
 
}
 
.yui-dt-editor .yui-dt-button button:active {
 
    background: url(../images/sprite.png) repeat-x 0 -1700px;
 
    color: #000;
 
}
 
.yui-skin-sam tr.yui-dt-even { background-color: #FFF }
 
.yui-skin-sam tr.yui-dt-odd { background-color: #edf5ff }
 
.yui-skin-sam tr.yui-dt-even td.yui-dt-asc,
 
.yui-skin-sam tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff }
 
.yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,
 
.yui-skin-sam tr.yui-dt-odd td.yui-dt-desc { background-color: #dbeaff }
 
.yui-skin-sam .yui-dt-list tr.yui-dt-even { background-color: #FFF }
 
.yui-skin-sam .yui-dt-list tr.yui-dt-odd { background-color: #FFF }
 
.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff }
 
.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc { background-color: #edf5ff }
 
.yui-skin-sam th.yui-dt-highlighted,
 
.yui-skin-sam th.yui-dt-highlighted a { background-color: #b2d2ff }
 
.yui-skin-sam tr.yui-dt-highlighted,
 
.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc,
 
.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc,
 
.yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted,
 
.yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted {
 
    cursor: pointer;
 
    background-color: #b2d2ff;
 
}
 
.yui-skin-sam .yui-dt-list th.yui-dt-highlighted,
 
.yui-skin-sam .yui-dt-list th.yui-dt-highlighted a { background-color: #b2d2ff }
 
.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted {
 
    cursor: pointer;
 
    background-color: #b2d2ff;
 
}
 
.yui-skin-sam th.yui-dt-selected,
 
.yui-skin-sam th.yui-dt-selected a { background-color: #446cd7 }
 
.yui-skin-sam tr.yui-dt-selected td,
 
.yui-skin-sam tr.yui-dt-selected td.yui-dt-asc,
 
.yui-skin-sam tr.yui-dt-selected td.yui-dt-desc {
 
    background-color: #426fd9;
 
    color: #FFF;
 
}
 
.yui-skin-sam tr.yui-dt-even td.yui-dt-selected,
 
.yui-skin-sam tr.yui-dt-odd td.yui-dt-selected {
 
    background-color: #446cd7;
 
    color: #FFF;
 
}
 
.yui-skin-sam .yui-dt-list th.yui-dt-selected,
 
.yui-skin-sam .yui-dt-list th.yui-dt-selected a { background-color: #446cd7 }
 
.yui-skin-sam .yui-dt-list tr.yui-dt-selected td,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc {
 
    background-color: #426fd9;
 
    color: #FFF;
 
}
 
.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected,
 
.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected {
 
    background-color: #446cd7;
 
    color: #FFF;
 
}
 
.yui-skin-sam .yui-dt-paginator {
 
    display: block;
 
    margin: 6px 0;
 
    white-space: nowrap;
 
}
 
.yui-skin-sam .yui-dt-paginator .yui-dt-first,
 
.yui-skin-sam .yui-dt-paginator .yui-dt-last,
 
.yui-skin-sam .yui-dt-paginator .yui-dt-selected { padding: 2px 6px }
 
.yui-skin-sam .yui-dt-paginator a.yui-dt-first,
 
.yui-skin-sam .yui-dt-paginator a.yui-dt-last { text-decoration: none }
 
.yui-skin-sam .yui-dt-paginator .yui-dt-previous,
 
.yui-skin-sam .yui-dt-paginator .yui-dt-next { display: none }
 
.yui-skin-sam a.yui-dt-page {
 
    border: 1px solid #cbcbcb;
 
    padding: 2px 6px;
 
    text-decoration: none;
 
    background-color: #fff;
 
}
 
.yui-skin-sam .yui-dt-selected {
 
    border: 1px solid #fff;
 
    background-color: #fff;
 
}
 

	
 
#content #left {
 
	left: 0;
 
	width: 280px;
 
	position: absolute;
 
    left: 0;
 
    width: 280px;
 
    position: absolute;
 
}
 

	
 
#content #right {
 
	margin: 0 60px 10px 290px;
 
    margin: 0 60px 10px 290px;
 
}
 

	
 
#content div.box {
 
	clear: both;
 
	overflow: hidden;
 
	background: #fff;
 
	margin: 0 0 10px;
 
	padding: 0 0 10px;
 
	-webkit-border-radius: 4px 4px 4px 4px;
 
	-khtml-border-radius: 4px 4px 4px 4px;
 
	-moz-border-radius: 4px 4px 4px 4px;
 
	border-radius: 4px 4px 4px 4px;
 
	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    clear: both;
 
    overflow: hidden;
 
    background: #fff;
 
    margin: 0 0 10px;
 
    padding: 0 0 10px;
 
    -webkit-border-radius: 4px 4px 4px 4px;
 
    -khtml-border-radius: 4px 4px 4px 4px;
 
    -moz-border-radius: 4px 4px 4px 4px;
 
    border-radius: 4px 4px 4px 4px;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
}
 

	
 
#content div.box-left {
 
	width: 49%;
 
	clear: none;
 
	float: left;
 
	margin: 0 0 10px;
 
    width: 49%;
 
    clear: none;
 
    float: left;
 
    margin: 0 0 10px;
 
}
 

	
 
#content div.box-right {
 
	width: 49%;
 
	clear: none;
 
	float: right;
 
	margin: 0 0 10px;
 
    width: 49%;
 
    clear: none;
 
    float: right;
 
    margin: 0 0 10px;
 
}
 

	
 
#content div.box div.title {
 
	clear: both;
 
	overflow: hidden;
 
	background-color: #003B76;
 
	background-repeat: repeat-x;
 
	background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
 
	background-image: -moz-linear-gradient(top, #003b76, #00376e);
 
	background-image: -ms-linear-gradient(top, #003b76, #00376e);
 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
 
	background-image: -webkit-linear-gradient(top, #003b76, #00376e);
 
	background-image: -o-linear-gradient(top, #003b76, #00376e);
 
	background-image: linear-gradient(top, #003b76, #00376e);
 
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
 
	margin: 0 0 20px;
 
	padding: 0;
 
    clear: both;
 
    overflow: hidden;
 
    background-color: #003B76;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
 
    background-image: -moz-linear-gradient(top, #003b76, #00376e);
 
    background-image: -ms-linear-gradient(top, #003b76, #00376e);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
 
    background-image: -webkit-linear-gradient(top, #003b76, #00376e);
 
    background-image: -o-linear-gradient(top, #003b76, #00376e);
 
    background-image: linear-gradient(top, #003b76, #00376e);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
 
    margin: 0 0 20px;
 
    padding: 0;
 
}
 

	
 
#content div.box div.title h5 {
 
	float: left;
 
	border: none;
 
	color: #fff;
 
	text-transform: uppercase;
 
	margin: 0;
 
	padding: 11px 0 11px 10px;
 
    float: left;
 
    border: none;
 
    color: #fff;
 
    text-transform: uppercase;
 
    margin: 0;
 
    padding: 11px 0 11px 10px;
 
}
 

	
 
#content div.box div.title .link-white{
 
	color: #FFFFFF;
 
    color: #FFFFFF;
 
}
 

	
 
#content div.box div.title .link-white.current{
 
    color: #BFE3FF;
 
}
 

	
 
#content div.box div.title ul.links li {
 
	list-style: none;
 
	float: left;
 
	margin: 0;
 
	padding: 0;
 
    list-style: none;
 
    float: left;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.title ul.links li a {
 
	border-left: 1px solid #316293;
 
	color: #FFFFFF;
 
	display: block;
 
	float: left;
 
	font-size: 13px;
 
	font-weight: 700;
 
	height: 1%;
 
	margin: 0;
 
	padding: 11px 22px 12px;
 
	text-decoration: none;
 
    border-left: 1px solid #316293;
 
    color: #FFFFFF;
 
    display: block;
 
    float: left;
 
    font-size: 13px;
 
    font-weight: 700;
 
    height: 1%;
 
    margin: 0;
 
    padding: 11px 22px 12px;
 
    text-decoration: none;
 
}
 

	
 
#content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6,
 
#content div.box div.h1,#content div.box div.h2,#content div.box div.h3,#content div.box div.h4,#content div.box div.h5,#content div.box div.h6
 

	
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	border-bottom: 1px solid #DDD;
 
	margin: 10px 20px;
 
	padding: 0 0 15px;
 
    {
 
    clear: both;
 
    overflow: hidden;
 
    border-bottom: 1px solid #DDD;
 
    margin: 10px 20px;
 
    padding: 0 0 15px;
 
}
 

	
 
#content div.box p {
 
	color: #5f5f5f;
 
	font-size: 12px;
 
	line-height: 150%;
 
	margin: 0 24px 10px;
 
	padding: 0;
 
    color: #5f5f5f;
 
    font-size: 12px;
 
    line-height: 150%;
 
    margin: 0 24px 10px;
 
    padding: 0;
 
}
 

	
 
#content div.box blockquote {
 
	border-left: 4px solid #DDD;
 
	color: #5f5f5f;
 
	font-size: 11px;
 
	line-height: 150%;
 
	margin: 0 34px;
 
	padding: 0 0 0 14px;
 
    border-left: 4px solid #DDD;
 
    color: #5f5f5f;
 
    font-size: 11px;
 
    line-height: 150%;
 
    margin: 0 34px;
 
    padding: 0 0 0 14px;
 
}
 

	
 
#content div.box blockquote p {
 
	margin: 10px 0;
 
	padding: 0;
 
    margin: 10px 0;
 
    padding: 0;
 
}
 

	
 
#content div.box dl {
 
	margin: 10px 0px;
 
    margin: 10px 0px;
 
}
 

	
 
#content div.box dt {
 
	font-size: 12px;
 
	margin: 0;
 
    font-size: 12px;
 
    margin: 0;
 
}
 

	
 
#content div.box dd {
 
	font-size: 12px;
 
	margin: 0;
 
	padding: 8px 0 8px 15px;
 
    font-size: 12px;
 
    margin: 0;
 
    padding: 8px 0 8px 15px;
 
}
 

	
 
#content div.box li {
 
	font-size: 12px;
 
	padding: 4px 0;
 
    font-size: 12px;
 
    padding: 4px 0;
 
}
 

	
 
#content div.box ul.disc,#content div.box ul.circle {
 
	margin: 10px 24px 10px 38px;
 
    margin: 10px 24px 10px 38px;
 
}
 

	
 
#content div.box ul.square {
 
	margin: 10px 24px 10px 40px;
 
    margin: 10px 24px 10px 40px;
 
}
 

	
 
#content div.box img.left {
 
	border: none;
 
	float: left;
 
	margin: 10px 10px 10px 0;
 
    border: none;
 
    float: left;
 
    margin: 10px 10px 10px 0;
 
}
 

	
 
#content div.box img.right {
 
	border: none;
 
	float: right;
 
	margin: 10px 0 10px 10px;
 
    border: none;
 
    float: right;
 
    margin: 10px 0 10px 10px;
 
}
 

	
 
#content div.box div.messages {
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0 20px;
 
	padding: 0;
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0 20px;
 
    padding: 0;
 
}
 

	
 
#content div.box div.message {
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0;
 
	padding: 5px 0;
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0;
 
    padding: 5px 0;
 
    white-space: pre-wrap;
 
}
 
#content div.box div.expand {
 
	width: 110%;
 
	height:14px;
 
	font-size:10px;
 
	text-align:center;
 
	cursor: pointer;
 
	color:#666;
 

	
 
	background:-webkit-gradient(linear,0% 50%,100% 50%,color-stop(0%,rgba(255,255,255,0)),color-stop(100%,rgba(64,96,128,0.1)));
 
	background:-webkit-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
	background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
	background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
	background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
	background:linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 

	
 
	display: none;
 
    width: 110%;
 
    height:14px;
 
    font-size:10px;
 
    text-align:center;
 
    cursor: pointer;
 
    color:#666;
 

	
 
    background:-webkit-gradient(linear,0% 50%,100% 50%,color-stop(0%,rgba(255,255,255,0)),color-stop(100%,rgba(64,96,128,0.1)));
 
    background:-webkit-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
    background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
    background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
    background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 
    background:linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
 

	
 
    display: none;
 
}
 
#content div.box div.expand .expandtext {
 
	background-color: #ffffff;
 
	padding: 2px;
 
	border-radius: 2px;
 
    background-color: #ffffff;
 
    padding: 2px;
 
    border-radius: 2px;
 
}
 

	
 
#content div.box div.message a {
 
	font-weight: 400 !important;
 
    font-weight: 400 !important;
 
}
 

	
 
#content div.box div.message div.image {
 
	float: left;
 
	margin: 9px 0 0 5px;
 
	padding: 6px;
 
    float: left;
 
    margin: 9px 0 0 5px;
 
    padding: 6px;
 
}
 

	
 
#content div.box div.message div.image img {
 
	vertical-align: middle;
 
	margin: 0;
 
    vertical-align: middle;
 
    margin: 0;
 
}
 

	
 
#content div.box div.message div.text {
 
	float: left;
 
	margin: 0;
 
	padding: 9px 6px;
 
    float: left;
 
    margin: 0;
 
    padding: 9px 6px;
 
}
 

	
 
#content div.box div.message div.dismiss a {
 
	height: 16px;
 
	width: 16px;
 
	display: block;
 
	background: url("../images/icons/cross.png") no-repeat;
 
	margin: 15px 14px 0 0;
 
	padding: 0;
 
    height: 16px;
 
    width: 16px;
 
    display: block;
 
    background: url("../images/icons/cross.png") no-repeat;
 
    margin: 15px 14px 0 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6
 
	{
 
	border: none;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    border: none;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.message div.text span {
 
	height: 1%;
 
	display: block;
 
	margin: 0;
 
	padding: 5px 0 0;
 
    height: 1%;
 
    display: block;
 
    margin: 0;
 
    padding: 5px 0 0;
 
}
 

	
 
#content div.box div.message-error {
 
	height: 1%;
 
	clear: both;
 
	overflow: hidden;
 
	background: #FBE3E4;
 
	border: 1px solid #FBC2C4;
 
	color: #860006;
 
    height: 1%;
 
    clear: both;
 
    overflow: hidden;
 
    background: #FBE3E4;
 
    border: 1px solid #FBC2C4;
 
    color: #860006;
 
}
 

	
 
#content div.box div.message-error h6 {
 
	color: #860006;
 
    color: #860006;
 
}
 

	
 
#content div.box div.message-warning {
 
	height: 1%;
 
	clear: both;
 
	overflow: hidden;
 
	background: #FFF6BF;
 
	border: 1px solid #FFD324;
 
	color: #5f5200;
 
    height: 1%;
 
    clear: both;
 
    overflow: hidden;
 
    background: #FFF6BF;
 
    border: 1px solid #FFD324;
 
    color: #5f5200;
 
}
 

	
 
#content div.box div.message-warning h6 {
 
	color: #5f5200;
 
    color: #5f5200;
 
}
 

	
 
#content div.box div.message-notice {
 
	height: 1%;
 
	clear: both;
 
	overflow: hidden;
 
	background: #8FBDE0;
 
	border: 1px solid #6BACDE;
 
	color: #003863;
 
    height: 1%;
 
    clear: both;
 
    overflow: hidden;
 
    background: #8FBDE0;
 
    border: 1px solid #6BACDE;
 
    color: #003863;
 
}
 

	
 
#content div.box div.message-notice h6 {
 
	color: #003863;
 
    color: #003863;
 
}
 

	
 
#content div.box div.message-success {
 
	height: 1%;
 
	clear: both;
 
	overflow: hidden;
 
	background: #E6EFC2;
 
	border: 1px solid #C6D880;
 
	color: #4e6100;
 
    height: 1%;
 
    clear: both;
 
    overflow: hidden;
 
    background: #E6EFC2;
 
    border: 1px solid #C6D880;
 
    color: #4e6100;
 
}
 

	
 
#content div.box div.message-success h6 {
 
	color: #4e6100;
 
    color: #4e6100;
 
}
 

	
 
#content div.box div.form div.fields div.field {
 
	height: 1%;
 
	border-bottom: 1px solid #DDD;
 
	clear: both;
 
	margin: 0;
 
	padding: 10px 0;
 
    height: 1%;
 
    border-bottom: 1px solid #DDD;
 
    clear: both;
 
    margin: 0;
 
    padding: 10px 0;
 
}
 

	
 
#content div.box div.form div.fields div.field-first {
 
	padding: 0 0 10px;
 
    padding: 0 0 10px;
 
}
 

	
 
#content div.box div.form div.fields div.field-noborder {
 
	border-bottom: 0 !important;
 
    border-bottom: 0 !important;
 
}
 

	
 
#content div.box div.form div.fields div.field span.error-message {
 
	height: 1%;
 
	display: inline-block;
 
	color: red;
 
	margin: 8px 0 0 4px;
 
	padding: 0;
 
    height: 1%;
 
    display: inline-block;
 
    color: red;
 
    margin: 8px 0 0 4px;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field span.success {
 
	height: 1%;
 
	display: block;
 
	color: #316309;
 
	margin: 8px 0 0;
 
	padding: 0;
 
    height: 1%;
 
    display: block;
 
    color: #316309;
 
    margin: 8px 0 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.label {
 
	left: 70px;
 
	width: 155px;
 
	position: absolute;
 
	margin: 0;
 
	padding: 5px 0 0 0px;
 
    left: 70px;
 
    width: 155px;
 
    position: absolute;
 
    margin: 0;
 
    padding: 5px 0 0 0px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.label-summary {
 
    left: 30px;
 
    width: 155px;
 
    position: absolute;
 
    margin: 0;
 
    padding: 0px 0 0 0px;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.label,
 
#content div.box-right div.form div.fields div.field div.label,
 
#content div.box-left div.form div.fields div.field div.label,
 
#content div.box-left div.form div.fields div.field div.label-summary,
 
#content div.box-right div.form div.fields div.field div.label-summary,
 
#content div.box-left div.form div.fields div.field div.label-summary
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	left: 0;
 
	width: auto;
 
	position: relative;
 
	margin: 0;
 
	padding: 0 0 8px;
 
    {
 
    clear: both;
 
    overflow: hidden;
 
    left: 0;
 
    width: auto;
 
    position: relative;
 
    margin: 0;
 
    padding: 0 0 8px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.label-select {
 
	padding: 5px 0 0 5px;
 
    padding: 5px 0 0 5px;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.label-select,
 
#content div.box-right div.form div.fields div.field div.label-select
 
	{
 
	padding: 0 0 8px;
 
    {
 
    padding: 0 0 8px;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.label-textarea,
 
#content div.box-right div.form div.fields div.field div.label-textarea
 
	{
 
	padding: 0 0 8px !important;
 
    {
 
    padding: 0 0 8px !important;
 
}
 

	
 
#content div.box div.form div.fields div.field div.label label,div.label label
 
	{
 
	color: #393939;
 
	font-weight: 700;
 
    {
 
    color: #393939;
 
    font-weight: 700;
 
}
 
#content div.box div.form div.fields div.field div.label label,div.label-summary label
 
    {
 
    color: #393939;
 
    font-weight: 700;
 
}
 
#content div.box div.form div.fields div.field div.input {
 
	margin: 0 0 0 200px;
 
    margin: 0 0 0 200px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input.summary {
 
    margin: 0 0 0 110px;
 
}
 
#content div.box div.form div.fields div.field div.input.summary-short {
 
    margin: 0 0 0 110px;
 
}
 
#content div.box div.form div.fields div.field div.file {
 
	margin: 0 0 0 200px;
 
    margin: 0 0 0 200px;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input
 
	{
 
	margin: 0 0 0 0px;
 
    {
 
    margin: 0 0 0 0px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input,
 
.reviewer_ac input {
 
	background: #FFF;
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	color: #000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 7px 7px 6px;
 
    background: #FFF;
 
    border-top: 1px solid #b3b3b3;
 
    border-left: 1px solid #b3b3b3;
 
    border-right: 1px solid #eaeaea;
 
    border-bottom: 1px solid #eaeaea;
 
    color: #000;
 
    font-size: 11px;
 
    margin: 0;
 
    padding: 7px 7px 6px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input#clone_url,
 
#content div.box div.form div.fields div.field div.input input#clone_url_id
 
{
 
    font-size: 16px;
 
    padding: 2px;	
 
    padding: 2px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.file input {
 
	background: none repeat scroll 0 0 #FFFFFF;
 
	border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
 
	border-style: solid;
 
	border-width: 1px;
 
	color: #000000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 7px 7px 6px;
 
    background: none repeat scroll 0 0 #FFFFFF;
 
    border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
 
    border-style: solid;
 
    border-width: 1px;
 
    color: #000000;
 
    font-size: 11px;
 
    margin: 0;
 
    padding: 7px 7px 6px;
 
}
 

	
 
input.disabled {
 
    background-color: #F5F5F5 !important;	
 
    background-color: #F5F5F5 !important;
 
}
 
#content div.box div.form div.fields div.field div.input input.small {
 
	width: 30%;
 
    width: 30%;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input.medium {
 
	width: 55%;
 
    width: 55%;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input.large {
 
	width: 85%;
 
    width: 85%;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input.date {
 
	width: 177px;
 
    width: 177px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input.button {
 
	background: #D4D0C8;
 
	border-top: 1px solid #FFF;
 
	border-left: 1px solid #FFF;
 
	border-right: 1px solid #404040;
 
	border-bottom: 1px solid #404040;
 
	color: #000;
 
	margin: 0;
 
	padding: 4px 8px;
 
    background: #D4D0C8;
 
    border-top: 1px solid #FFF;
 
    border-left: 1px solid #FFF;
 
    border-right: 1px solid #404040;
 
    border-bottom: 1px solid #404040;
 
    color: #000;
 
    margin: 0;
 
    padding: 4px 8px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea {
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	margin: 0 0 0 200px;
 
	padding: 10px;
 
    border-top: 1px solid #b3b3b3;
 
    border-left: 1px solid #b3b3b3;
 
    border-right: 1px solid #eaeaea;
 
    border-bottom: 1px solid #eaeaea;
 
    margin: 0 0 0 200px;
 
    padding: 10px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea-editor {
 
	border: 1px solid #ddd;
 
	padding: 0;
 
    border: 1px solid #ddd;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea textarea {
 
	width: 100%;
 
	height: 220px;
 
	overflow: hidden;
 
	background: #FFF;
 
	color: #000;
 
	font-size: 11px;
 
	outline: none;
 
	border-width: 0;
 
	margin: 0;
 
	padding: 0;
 
    width: 100%;
 
    height: 220px;
 
    overflow: hidden;
 
    background: #FFF;
 
    color: #000;
 
    font-size: 11px;
 
    outline: none;
 
    border-width: 0;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea
 
	{
 
	width: 100%;
 
	height: 100px;
 
    {
 
    width: 100%;
 
    height: 100px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea table {
 
	width: 100%;
 
	border: none;
 
	margin: 0;
 
	padding: 0;
 
    width: 100%;
 
    border: none;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea table td {
 
	background: #DDD;
 
	border: none;
 
	padding: 0;
 
    background: #DDD;
 
    border: none;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea table td table
 
	{
 
	width: auto;
 
	border: none;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    width: auto;
 
    border: none;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.textarea table td table td
 
	{
 
	font-size: 11px;
 
	padding: 5px 5px 5px 0;
 
    {
 
    font-size: 11px;
 
    padding: 5px 5px 5px 0;
 
}
 

	
 
#content div.box div.form div.fields div.field input[type=text]:focus,
 
#content div.box div.form div.fields div.field input[type=password]:focus,
 
#content div.box div.form div.fields div.field input[type=file]:focus,
 
#content div.box div.form div.fields div.field textarea:focus,
 
#content div.box div.form div.fields div.field select:focus,
 
.reviewer_ac input:focus
 
	{
 
	background: #f6f6f6;
 
	border-color: #666;
 
    {
 
    background: #f6f6f6;
 
    border-color: #666;
 
}
 

	
 
.reviewer_ac {
 
	padding:10px
 
    padding:10px
 
}
 

	
 
div.form div.fields div.field div.button {
 
	margin: 0;
 
	padding: 0 0 0 8px;
 
    margin: 0;
 
    padding: 0 0 0 8px;
 
}
 
#content div.box table.noborder {
 
	border: 1px solid transparent;
 
    border: 1px solid transparent;
 
}
 

	
 
#content div.box table {
 
	width: 100%;
 
	border-collapse: separate;
 
	margin: 0;
 
	padding: 0;
 
	border: 1px solid #eee;
 
    width: 100%;
 
    border-collapse: separate;
 
    margin: 0;
 
    padding: 0;
 
    border: 1px solid #eee;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;	
 
    border-radius: 4px;
 
}
 

	
 
#content div.box table th {
 
	background: #eee;
 
	border-bottom: 1px solid #ddd;
 
	padding: 5px 0px 5px 5px;
 
	text-align: left;
 
    background: #eee;
 
    border-bottom: 1px solid #ddd;
 
    padding: 5px 0px 5px 5px;
 
    text-align: left;
 
}
 

	
 
#content div.box table th.left {
 
	text-align: left;
 
    text-align: left;
 
}
 

	
 
#content div.box table th.right {
 
	text-align: right;
 
    text-align: right;
 
}
 

	
 
#content div.box table th.center {
 
	text-align: center;
 
    text-align: center;
 
}
 

	
 
#content div.box table th.selected {
 
	vertical-align: middle;
 
	padding: 0;
 
    vertical-align: middle;
 
    padding: 0;
 
}
 

	
 
#content div.box table td {
 
	background: #fff;
 
	border-bottom: 1px solid #cdcdcd;
 
	vertical-align: middle;
 
	padding: 5px;
 
    background: #fff;
 
    border-bottom: 1px solid #cdcdcd;
 
    vertical-align: middle;
 
    padding: 5px;
 
}
 

	
 
#content div.box table tr.selected td {
 
	background: #FFC;
 
    background: #FFC;
 
}
 

	
 
#content div.box table td.selected {
 
	width: 3%;
 
	text-align: center;
 
	vertical-align: middle;
 
	padding: 0;
 
    width: 3%;
 
    text-align: center;
 
    vertical-align: middle;
 
    padding: 0;
 
}
 

	
 
#content div.box table td.action {
 
	width: 45%;
 
	text-align: left;
 
    width: 45%;
 
    text-align: left;
 
}
 

	
 
#content div.box table td.date {
 
	width: 33%;
 
	text-align: center;
 
    width: 33%;
 
    text-align: center;
 
}
 

	
 
#content div.box div.action {
 
	float: right;
 
	background: #FFF;
 
	text-align: right;
 
	margin: 10px 0 0;
 
	padding: 0;
 
    float: right;
 
    background: #FFF;
 
    text-align: right;
 
    margin: 10px 0 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.action select {
 
	font-size: 11px;
 
	margin: 0;
 
    font-size: 11px;
 
    margin: 0;
 
}
 

	
 
#content div.box div.action .ui-selectmenu {
 
	margin: 0;
 
	padding: 0;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.pagination {
 
	height: 1%;
 
	clear: both;
 
	overflow: hidden;
 
	margin: 10px 0 0;
 
	padding: 0;
 
    height: 1%;
 
    clear: both;
 
    overflow: hidden;
 
    margin: 10px 0 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.pagination ul.pager {
 
	float: right;
 
	text-align: right;
 
	margin: 0;
 
	padding: 0;
 
    float: right;
 
    text-align: right;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.pagination ul.pager li {
 
	height: 1%;
 
	float: left;
 
	list-style: none;
 
	background: #ebebeb url("../images/pager.png") repeat-x;
 
	border-top: 1px solid #dedede;
 
	border-left: 1px solid #cfcfcf;
 
	border-right: 1px solid #c4c4c4;
 
	border-bottom: 1px solid #c4c4c4;
 
	color: #4A4A4A;
 
	font-weight: 700;
 
	margin: 0 0 0 4px;
 
	padding: 0;
 
    height: 1%;
 
    float: left;
 
    list-style: none;
 
    background: #ebebeb url("../images/pager.png") repeat-x;
 
    border-top: 1px solid #dedede;
 
    border-left: 1px solid #cfcfcf;
 
    border-right: 1px solid #c4c4c4;
 
    border-bottom: 1px solid #c4c4c4;
 
    color: #4A4A4A;
 
    font-weight: 700;
 
    margin: 0 0 0 4px;
 
    padding: 0;
 
}
 

	
 
#content div.box div.pagination ul.pager li.separator {
 
	padding: 6px;
 
    padding: 6px;
 
}
 

	
 
#content div.box div.pagination ul.pager li.current {
 
	background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
	border-top: 1px solid #ccc;
 
	border-left: 1px solid #bebebe;
 
	border-right: 1px solid #b1b1b1;
 
	border-bottom: 1px solid #afafaf;
 
	color: #515151;
 
	padding: 6px;
 
    background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
    border-top: 1px solid #ccc;
 
    border-left: 1px solid #bebebe;
 
    border-right: 1px solid #b1b1b1;
 
    border-bottom: 1px solid #afafaf;
 
    color: #515151;
 
    padding: 6px;
 
}
 

	
 
#content div.box div.pagination ul.pager li a {
 
	height: 1%;
 
	display: block;
 
	float: left;
 
	color: #515151;
 
	text-decoration: none;
 
	margin: 0;
 
	padding: 6px;
 
    height: 1%;
 
    display: block;
 
    float: left;
 
    color: #515151;
 
    text-decoration: none;
 
    margin: 0;
 
    padding: 6px;
 
}
 

	
 
#content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active
 
	{
 
	background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
	border-top: 1px solid #ccc;
 
	border-left: 1px solid #bebebe;
 
	border-right: 1px solid #b1b1b1;
 
	border-bottom: 1px solid #afafaf;
 
	margin: -1px;
 
    {
 
    background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
    border-top: 1px solid #ccc;
 
    border-left: 1px solid #bebebe;
 
    border-right: 1px solid #b1b1b1;
 
    border-bottom: 1px solid #afafaf;
 
    margin: -1px;
 
}
 

	
 
#content div.box div.pagination-wh {
 
	height: 1%;
 
	clear: both;
 
	overflow: hidden;
 
	text-align: right;
 
	margin: 10px 0 0;
 
	padding: 0;
 
    height: 1%;
 
    clear: both;
 
    overflow: hidden;
 
    text-align: right;
 
    margin: 10px 0 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.pagination-right {
 
	float: right;
 
    float: right;
 
}
 

	
 
#content div.box div.pagination-wh a,
 
#content div.box div.pagination-wh span.pager_dotdot,
 
#content div.box div.pagination-wh span.yui-pg-previous,
 
#content div.box div.pagination-wh span.yui-pg-last,
 
#content div.box div.pagination-wh span.yui-pg-next,
 
#content div.box div.pagination-wh span.yui-pg-first
 
	{
 
	height: 1%;
 
	float: left;
 
	background: #ebebeb url("../images/pager.png") repeat-x;
 
	border-top: 1px solid #dedede;
 
	border-left: 1px solid #cfcfcf;
 
	border-right: 1px solid #c4c4c4;
 
	border-bottom: 1px solid #c4c4c4;
 
	color: #4A4A4A;
 
	font-weight: 700;
 
	margin: 0 0 0 4px;
 
	padding: 6px;
 
    {
 
    height: 1%;
 
    float: left;
 
    background: #ebebeb url("../images/pager.png") repeat-x;
 
    border-top: 1px solid #dedede;
 
    border-left: 1px solid #cfcfcf;
 
    border-right: 1px solid #c4c4c4;
 
    border-bottom: 1px solid #c4c4c4;
 
    color: #4A4A4A;
 
    font-weight: 700;
 
    margin: 0 0 0 4px;
 
    padding: 6px;
 
}
 

	
 
#content div.box div.pagination-wh span.pager_curpage {
 
	height: 1%;
 
	float: left;
 
	background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
	border-top: 1px solid #ccc;
 
	border-left: 1px solid #bebebe;
 
	border-right: 1px solid #b1b1b1;
 
	border-bottom: 1px solid #afafaf;
 
	color: #515151;
 
	font-weight: 700;
 
	margin: 0 0 0 4px;
 
	padding: 6px;
 
    height: 1%;
 
    float: left;
 
    background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
    border-top: 1px solid #ccc;
 
    border-left: 1px solid #bebebe;
 
    border-right: 1px solid #b1b1b1;
 
    border-bottom: 1px solid #afafaf;
 
    color: #515151;
 
    font-weight: 700;
 
    margin: 0 0 0 4px;
 
    padding: 6px;
 
}
 

	
 
#content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active
 
	{
 
	background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
	border-top: 1px solid #ccc;
 
	border-left: 1px solid #bebebe;
 
	border-right: 1px solid #b1b1b1;
 
	border-bottom: 1px solid #afafaf;
 
	text-decoration: none;
 
    {
 
    background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
 
    border-top: 1px solid #ccc;
 
    border-left: 1px solid #bebebe;
 
    border-right: 1px solid #b1b1b1;
 
    border-bottom: 1px solid #afafaf;
 
    text-decoration: none;
 
}
 

	
 
#content div.box div.traffic div.legend {
 
	clear: both;
 
	overflow: hidden;
 
	border-bottom: 1px solid #ddd;
 
	margin: 0 0 10px;
 
	padding: 0 0 10px;
 
    clear: both;
 
    overflow: hidden;
 
    border-bottom: 1px solid #ddd;
 
    margin: 0 0 10px;
 
    padding: 0 0 10px;
 
}
 

	
 
#content div.box div.traffic div.legend h6 {
 
	float: left;
 
	border: none;
 
	margin: 0;
 
	padding: 0;
 
    float: left;
 
    border: none;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.traffic div.legend li {
 
	list-style: none;
 
	float: left;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 0 8px 0 4px;
 
    list-style: none;
 
    float: left;
 
    font-size: 11px;
 
    margin: 0;
 
    padding: 0 8px 0 4px;
 
}
 

	
 
#content div.box div.traffic div.legend li.visits {
 
	border-left: 12px solid #edc240;
 
    border-left: 12px solid #edc240;
 
}
 

	
 
#content div.box div.traffic div.legend li.pageviews {
 
	border-left: 12px solid #afd8f8;
 
    border-left: 12px solid #afd8f8;
 
}
 

	
 
#content div.box div.traffic table {
 
	width: auto;
 
    width: auto;
 
}
 

	
 
#content div.box div.traffic table td {
 
	background: transparent;
 
	border: none;
 
	padding: 2px 3px 3px;
 
    background: transparent;
 
    border: none;
 
    padding: 2px 3px 3px;
 
}
 

	
 
#content div.box div.traffic table td.legendLabel {
 
	padding: 0 3px 2px;
 
    padding: 0 3px 2px;
 
}
 

	
 
#summary {
 
	
 
}
 

	
 
#summary .metatag {
 
    display: inline-block;
 
    padding: 3px 5px;
 
    margin-bottom: 3px;
 
    margin-right: 1px;
 
    border-radius: 5px;
 
}
 

	
 
#content div.box #summary p {
 
    margin-bottom: -5px;
 
        width: 600px;
 
        white-space: pre-wrap;
 
}
 

	
 
#content div.box #summary p:last-child {
 
    margin-bottom: 9px;
 
}
 

	
 
#content div.box #summary p:first-of-type {
 
    margin-top: 9px;
 
}
 

	
 
 .metatag {
 
    display: inline-block;
 
    margin-right: 1px;
 
    -webkit-border-radius: 4px 4px 4px 4px;
 
    -khtml-border-radius: 4px 4px 4px 4px;
 
    -moz-border-radius: 4px 4px 4px 4px;
 
    border-radius: 4px 4px 4px 4px;
 
    
 

	
 
    border: solid 1px #9CF;
 
    padding: 2px 3px 2px 3px !important;
 
    background-color: #DEF;    
 
    background-color: #DEF;
 
}
 

	
 
.metatag[tag="dead"] {
 
	background-color: #E44;
 
    background-color: #E44;
 
}
 

	
 
.metatag[tag="stale"] {
 
    background-color: #EA4;
 
}
 

	
 
.metatag[tag="featured"] {
 
	background-color: #AEA;
 
}
 

	
 
.metatag[tag="requires"] { 
 
	background-color: #9CF;
 
}
 

	
 
.metatag[tag="recommends"] { 
 
	background-color: #BDF; 
 
}
 

	
 
.metatag[tag="lang"] { 
 
    background-color: #FAF474; 
 
    background-color: #AEA;
 
}
 

	
 
.metatag[tag="requires"] {
 
    background-color: #9CF;
 
}
 

	
 
.metatag[tag="recommends"] {
 
    background-color: #BDF;
 
}
 

	
 
.metatag[tag="lang"] {
 
    background-color: #FAF474;
 
}
 

	
 
.metatag[tag="license"] {
 
    border: solid 1px #9CF;
 
    background-color: #DEF;
 
    target-new: tab !important;
 
}
 
.metatag[tag="see"] {
 
    border: solid 1px #CBD;
 
    background-color: #EDF;
 
}
 

	
 
a.metatag[tag="license"]:hover {
 
    background-color: #003367;
 
    color: #FFF;
 
    text-decoration: none;
 
}
 

	
 
#summary .desc {
 
	white-space: pre;
 
	width: 100%;
 
    white-space: pre;
 
    width: 100%;
 
}
 

	
 
#summary .repo_name {
 
	font-size: 1.6em;
 
	font-weight: bold;
 
	vertical-align: baseline;
 
	clear: right
 
    font-size: 1.6em;
 
    font-weight: bold;
 
    vertical-align: baseline;
 
    clear: right
 
}
 

	
 
#footer {
 
	clear: both;
 
	overflow: hidden;
 
	text-align: right;
 
	margin: 0;
 
	padding: 0 10px 4px;
 
	margin: -10px 0 0;
 
    clear: both;
 
    overflow: hidden;
 
    text-align: right;
 
    margin: 0;
 
    padding: 0 10px 4px;
 
    margin: -10px 0 0;
 
}
 

	
 
#footer div#footer-inner {
 
	background-color: #003B76; 
 
	background-repeat : repeat-x;
 
	background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E)); 
 
	background-image : -moz-linear-gradient(top, #003b76, #00376e); 
 
	background-image : -ms-linear-gradient( top, #003b76, #00376e); 
 
	background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
 
	background-image : -webkit-linear-gradient( top, #003b76, #00376e));
 
	background-image : -o-linear-gradient( top, #003b76, #00376e));
 
	background-image : linear-gradient( top, #003b76, #00376e); 
 
	filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
 
	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
	-webkit-border-radius: 4px 4px 4px 4px;
 
	-khtml-border-radius: 4px 4px 4px 4px;
 
	-moz-border-radius: 4px 4px 4px 4px;
 
	border-radius: 4px 4px 4px 4px;
 
    background-color: #003B76;
 
    background-repeat : repeat-x;
 
    background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E));
 
    background-image : -moz-linear-gradient(top, #003b76, #00376e);
 
    background-image : -ms-linear-gradient( top, #003b76, #00376e);
 
    background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
 
    background-image : -webkit-linear-gradient( top, #003b76, #00376e));
 
    background-image : -o-linear-gradient( top, #003b76, #00376e));
 
    background-image : linear-gradient( top, #003b76, #00376e);
 
    filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    -webkit-border-radius: 4px 4px 4px 4px;
 
    -khtml-border-radius: 4px 4px 4px 4px;
 
    -moz-border-radius: 4px 4px 4px 4px;
 
    border-radius: 4px 4px 4px 4px;
 
}
 

	
 
#footer div#footer-inner p {
 
	padding: 15px 25px 15px 0;
 
	color: #FFF;
 
	font-weight: 700;
 
    padding: 15px 25px 15px 0;
 
    color: #FFF;
 
    font-weight: 700;
 
}
 

	
 
#footer div#footer-inner .footer-link {
 
	float: left;
 
	padding-left: 10px;
 
    float: left;
 
    padding-left: 10px;
 
}
 

	
 
#footer div#footer-inner .footer-link a,#footer div#footer-inner .footer-link-right a
 
	{
 
	color: #FFF;
 
    {
 
    color: #FFF;
 
}
 

	
 
#login div.title {
 
	clear: both;
 
	overflow: hidden;
 
	position: relative;
 
	background-color: #003B76; 
 
	background-repeat : repeat-x;
 
	background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E)); 
 
	background-image : -moz-linear-gradient( top, #003b76, #00376e); 
 
	background-image : -ms-linear-gradient( top, #003b76, #00376e);
 
	background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
 
	background-image : -webkit-linear-gradient( top, #003b76, #00376e));
 
	background-image : -o-linear-gradient( top, #003b76, #00376e));
 
	background-image : linear-gradient( top, #003b76, #00376e); 
 
	filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
 
	margin: 0 auto;
 
	padding: 0;
 
    clear: both;
 
    overflow: hidden;
 
    position: relative;
 
    background-color: #003B76;
 
    background-repeat : repeat-x;
 
    background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E));
 
    background-image : -moz-linear-gradient( top, #003b76, #00376e);
 
    background-image : -ms-linear-gradient( top, #003b76, #00376e);
 
    background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
 
    background-image : -webkit-linear-gradient( top, #003b76, #00376e));
 
    background-image : -o-linear-gradient( top, #003b76, #00376e));
 
    background-image : linear-gradient( top, #003b76, #00376e);
 
    filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
 
    margin: 0 auto;
 
    padding: 0;
 
}
 

	
 
#login div.inner {
 
	background: #FFF url("../images/login.png") no-repeat top left;
 
	border-top: none;
 
	border-bottom: none;
 
	margin: 0 auto;
 
	padding: 20px;
 
    background: #FFF url("../images/login.png") no-repeat top left;
 
    border-top: none;
 
    border-bottom: none;
 
    margin: 0 auto;
 
    padding: 20px;
 
}
 

	
 
#login div.form div.fields div.field div.label {
 
	width: 173px;
 
	float: left;
 
	text-align: right;
 
	margin: 2px 10px 0 0;
 
	padding: 5px 0 0 5px;
 
    width: 173px;
 
    float: left;
 
    text-align: right;
 
    margin: 2px 10px 0 0;
 
    padding: 5px 0 0 5px;
 
}
 

	
 
#login div.form div.fields div.field div.input input {
 
	background: #FFF;
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	color: #000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 7px 7px 6px;
 
    background: #FFF;
 
    border-top: 1px solid #b3b3b3;
 
    border-left: 1px solid #b3b3b3;
 
    border-right: 1px solid #eaeaea;
 
    border-bottom: 1px solid #eaeaea;
 
    color: #000;
 
    font-size: 11px;
 
    margin: 0;
 
    padding: 7px 7px 6px;
 
}
 

	
 
#login div.form div.fields div.buttons {
 
	clear: both;
 
	overflow: hidden;
 
	border-top: 1px solid #DDD;
 
	text-align: right;
 
	margin: 0;
 
	padding: 10px 0 0;
 
    clear: both;
 
    overflow: hidden;
 
    border-top: 1px solid #DDD;
 
    text-align: right;
 
    margin: 0;
 
    padding: 10px 0 0;
 
}
 

	
 
#login div.form div.links {
 
	clear: both;
 
	overflow: hidden;
 
	margin: 10px 0 0;
 
	padding: 0 0 2px;
 
    clear: both;
 
    overflow: hidden;
 
    margin: 10px 0 0;
 
    padding: 0 0 2px;
 
}
 

	
 
.user-menu{
 
    margin: 0px !important;
 
    float: left;
 
}
 

	
 
.user-menu .container{
 
    padding:0px 4px 0px 4px;
 
    margin: 0px 0px 0px 0px;
 
}
 

	
 
.user-menu .gravatar{
 
    margin: 0px 0px 0px 0px;
 
    cursor: pointer;
 
}
 
.user-menu .gravatar.enabled{
 
	background-color: #FDF784 !important;
 
    background-color: #FDF784 !important;
 
}
 
.user-menu .gravatar:hover{
 
    background-color: #FDF784 !important; 
 
    background-color: #FDF784 !important;
 
}
 
#quick_login{
 
    min-height: 80px;
 
    padding: 4px;
 
    position: absolute;
 
    right: 0;
 
    width: 278px;
 
    background-color: #003B76;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
 
    background-image: -moz-linear-gradient(top, #003b76, #00376e);
 
    background-image: -ms-linear-gradient(top, #003b76, #00376e);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
 
    background-image: -webkit-linear-gradient(top, #003b76, #00376e);
 
    background-image: -o-linear-gradient(top, #003b76, #00376e);
 
    background-image: linear-gradient(top, #003b76, #00376e);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
 

	
 
	z-index: 999;
 
	-webkit-border-radius: 0px 0px 4px 4px;
 
	-khtml-border-radius: 0px 0px 4px 4px;
 
	-moz-border-radius: 0px 0px 4px 4px;
 
	border-radius: 0px 0px 4px 4px;
 
	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    z-index: 999;
 
    -webkit-border-radius: 0px 0px 4px 4px;
 
    -khtml-border-radius: 0px 0px 4px 4px;
 
    -moz-border-radius: 0px 0px 4px 4px;
 
    border-radius: 0px 0px 4px 4px;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
}
 
#quick_login h4{
 
    color: #fff;
 
    padding: 5px 0px 5px 14px;
 
}
 

	
 
#quick_login .password_forgoten {
 
	padding-right: 10px;
 
	padding-top: 0px;
 
	text-align: left;
 
    padding-right: 10px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
#quick_login .password_forgoten a {
 
	font-size: 10px;
 
	color: #fff;
 
    font-size: 10px;
 
    color: #fff;
 
}
 

	
 
#quick_login .register {
 
	padding-right: 10px;
 
	padding-top: 5px;
 
	text-align: left;
 
    padding-right: 10px;
 
    padding-top: 5px;
 
    text-align: left;
 
}
 

	
 
#quick_login .register a {
 
	font-size: 10px;
 
	color: #fff;
 
    font-size: 10px;
 
    color: #fff;
 
}
 

	
 
#quick_login .submit {
 
    margin: -20px 0 0 0px;
 
    position: absolute;
 
    right: 15px;
 
}
 

	
 
#quick_login .links_left{
 
	float: left;
 
    float: left;
 
}
 
#quick_login .links_right{
 
    float: right;
 
}
 
#quick_login .full_name{
 
    color: #FFFFFF;
 
    font-weight: bold;
 
    padding: 3px;
 
}
 
#quick_login .big_gravatar{
 
	padding:4px 0px 0px 6px;
 
    padding:4px 0px 0px 6px;
 
}
 
#quick_login .inbox{
 
    padding:4px 0px 0px 6px;
 
    color: #FFFFFF;
 
    font-weight: bold;    
 
    font-weight: bold;
 
}
 
#quick_login .inbox a{
 
	color: #FFFFFF;
 
    color: #FFFFFF;
 
}
 
#quick_login .email,#quick_login .email a{
 
    color: #FFFFFF;
 
    padding: 3px;
 
    
 

	
 
}
 
#quick_login .links .logout{
 

	
 
}
 

	
 
#quick_login div.form div.fields {
 
	padding-top: 2px;
 
	padding-left: 10px;
 
    padding-top: 2px;
 
    padding-left: 10px;
 
}
 

	
 
#quick_login div.form div.fields div.field {
 
	padding: 5px;
 
    padding: 5px;
 
}
 

	
 
#quick_login div.form div.fields div.field div.label label {
 
	color: #fff;
 
	padding-bottom: 3px;
 
    color: #fff;
 
    padding-bottom: 3px;
 
}
 

	
 
#quick_login div.form div.fields div.field div.input input {
 
	width: 236px;
 
	background: #FFF;
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	color: #000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 5px 7px 4px;
 
    width: 236px;
 
    background: #FFF;
 
    border-top: 1px solid #b3b3b3;
 
    border-left: 1px solid #b3b3b3;
 
    border-right: 1px solid #eaeaea;
 
    border-bottom: 1px solid #eaeaea;
 
    color: #000;
 
    font-size: 11px;
 
    margin: 0;
 
    padding: 5px 7px 4px;
 
}
 

	
 
#quick_login div.form div.fields div.buttons {
 
	clear: both;
 
	overflow: hidden;
 
	text-align: right;
 
	margin: 0;
 
	padding: 5px 14px 0px 5px;
 
    clear: both;
 
    overflow: hidden;
 
    text-align: right;
 
    margin: 0;
 
    padding: 5px 14px 0px 5px;
 
}
 

	
 
#quick_login div.form div.links {
 
	clear: both;
 
	overflow: hidden;
 
	margin: 10px 0 0;
 
	padding: 0 0 2px;
 
    clear: both;
 
    overflow: hidden;
 
    margin: 10px 0 0;
 
    padding: 0 0 2px;
 
}
 

	
 
#quick_login ol.links{
 
    display: block;
 
    font-weight: bold;
 
    list-style: none outside none;
 
    text-align: right;
 
}
 
#quick_login ol.links li{
 
    line-height: 27px;
 
    margin: 0;
 
    padding: 0;
 
    color: #fff;
 
    display: block;
 
    float:none !important;
 
}
 

	
 
#quick_login ol.links li a{
 
    color: #fff;
 
    display: block;
 
    padding: 2px;
 
}
 
#quick_login ol.links li a:HOVER{
 
    background-color: inherit !important;
 
}
 

	
 
#register div.title {
 
	clear: both;
 
	overflow: hidden;
 
	position: relative;
 
    clear: both;
 
    overflow: hidden;
 
    position: relative;
 
    background-color: #003B76;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
 
    background-image: -moz-linear-gradient(top, #003b76, #00376e);
 
    background-image: -ms-linear-gradient(top, #003b76, #00376e);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
 
    background-image: -webkit-linear-gradient(top, #003b76, #00376e);
 
    background-image: -o-linear-gradient(top, #003b76, #00376e);
 
    background-image: linear-gradient(top, #003b76, #00376e);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',
 
        endColorstr='#00376e', GradientType=0 );
 
	margin: 0 auto;
 
	padding: 0;
 
    margin: 0 auto;
 
    padding: 0;
 
}
 

	
 
#register div.inner {
 
	background: #FFF;
 
	border-top: none;
 
	border-bottom: none;
 
	margin: 0 auto;
 
	padding: 20px;
 
    background: #FFF;
 
    border-top: none;
 
    border-bottom: none;
 
    margin: 0 auto;
 
    padding: 20px;
 
}
 

	
 
#register div.form div.fields div.field div.label {
 
	width: 135px;
 
	float: left;
 
	text-align: right;
 
	margin: 2px 10px 0 0;
 
	padding: 5px 0 0 5px;
 
    width: 135px;
 
    float: left;
 
    text-align: right;
 
    margin: 2px 10px 0 0;
 
    padding: 5px 0 0 5px;
 
}
 

	
 
#register div.form div.fields div.field div.input input {
 
	width: 300px;
 
	background: #FFF;
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	color: #000;
 
	font-size: 11px;
 
	margin: 0;
 
	padding: 7px 7px 6px;
 
    width: 300px;
 
    background: #FFF;
 
    border-top: 1px solid #b3b3b3;
 
    border-left: 1px solid #b3b3b3;
 
    border-right: 1px solid #eaeaea;
 
    border-bottom: 1px solid #eaeaea;
 
    color: #000;
 
    font-size: 11px;
 
    margin: 0;
 
    padding: 7px 7px 6px;
 
}
 

	
 
#register div.form div.fields div.buttons {
 
	clear: both;
 
	overflow: hidden;
 
	border-top: 1px solid #DDD;
 
	text-align: left;
 
	margin: 0;
 
	padding: 10px 0 0 150px;
 
    clear: both;
 
    overflow: hidden;
 
    border-top: 1px solid #DDD;
 
    text-align: left;
 
    margin: 0;
 
    padding: 10px 0 0 150px;
 
}
 

	
 
#register div.form div.activation_msg {
 
	padding-top: 4px;
 
	padding-bottom: 4px;
 
    padding-top: 4px;
 
    padding-bottom: 4px;
 
}
 

	
 
#journal .journal_day {
 
	font-size: 20px;
 
	padding: 10px 0px;
 
	border-bottom: 2px solid #DDD;
 
	margin-left: 10px;
 
	margin-right: 10px;
 
    font-size: 20px;
 
    padding: 10px 0px;
 
    border-bottom: 2px solid #DDD;
 
    margin-left: 10px;
 
    margin-right: 10px;
 
}
 

	
 
#journal .journal_container {
 
	padding: 5px;
 
	clear: both;
 
	margin: 0px 5px 0px 10px;
 
    padding: 5px;
 
    clear: both;
 
    margin: 0px 5px 0px 10px;
 
}
 

	
 
#journal .journal_action_container {
 
	padding-left: 38px;
 
    padding-left: 38px;
 
}
 

	
 
#journal .journal_user {
 
	color: #747474;
 
	font-size: 14px;
 
	font-weight: bold;
 
	height: 30px;
 
    color: #747474;
 
    font-size: 14px;
 
    font-weight: bold;
 
    height: 30px;
 
}
 

	
 
#journal .journal_user.deleted {
 
    color: #747474;
 
    font-size: 14px;
 
    font-weight: normal;
 
    height: 30px;
 
    font-style: italic;
 
}
 

	
 

	
 
#journal .journal_icon {
 
	clear: both;
 
	float: left;
 
	padding-right: 4px;
 
	padding-top: 3px;
 
    clear: both;
 
    float: left;
 
    padding-right: 4px;
 
    padding-top: 3px;
 
}
 

	
 
#journal .journal_action {
 
	padding-top: 4px;
 
	min-height: 2px;
 
	float: left
 
    padding-top: 4px;
 
    min-height: 2px;
 
    float: left
 
}
 

	
 
#journal .journal_action_params {
 
	clear: left;
 
	padding-left: 22px;
 
    clear: left;
 
    padding-left: 22px;
 
}
 

	
 
#journal .journal_repo {
 
	float: left;
 
	margin-left: 6px;
 
	padding-top: 3px;
 
    float: left;
 
    margin-left: 6px;
 
    padding-top: 3px;
 
}
 

	
 
#journal .date {
 
	clear: both;
 
	color: #777777;
 
	font-size: 11px;
 
	padding-left: 22px;
 
    clear: both;
 
    color: #777777;
 
    font-size: 11px;
 
    padding-left: 22px;
 
}
 

	
 
#journal .journal_repo .journal_repo_name {
 
	font-weight: bold;
 
	font-size: 1.1em;
 
    font-weight: bold;
 
    font-size: 1.1em;
 
}
 

	
 
#journal .compare_view {
 
	padding: 5px 0px 5px 0px;
 
	width: 95px;
 
    padding: 5px 0px 5px 0px;
 
    width: 95px;
 
}
 

	
 
.journal_highlight {
 
	font-weight: bold;
 
	padding: 0 2px;
 
	vertical-align: bottom;
 
    font-weight: bold;
 
    padding: 0 2px;
 
    vertical-align: bottom;
 
}
 

	
 
.trending_language_tbl,.trending_language_tbl td {
 
	border: 0 !important;
 
	margin: 0 !important;
 
	padding: 0 !important;
 
    border: 0 !important;
 
    margin: 0 !important;
 
    padding: 0 !important;
 
}
 

	
 
.trending_language_tbl,.trending_language_tbl tr {
 
    border-spacing: 1px;
 
}
 

	
 
.trending_language {
 
	background-color: #003367;
 
	color: #FFF;
 
	display: block;
 
	min-width: 20px;
 
	text-decoration: none;
 
	height: 12px;
 
	margin-bottom: 0px;
 
	margin-left: 5px;
 
	white-space: pre;
 
	padding: 3px;
 
    background-color: #003367;
 
    color: #FFF;
 
    display: block;
 
    min-width: 20px;
 
    text-decoration: none;
 
    height: 12px;
 
    margin-bottom: 0px;
 
    margin-left: 5px;
 
    white-space: pre;
 
    padding: 3px;
 
}
 

	
 
h3.files_location {
 
	font-size: 1.8em;
 
	font-weight: 700;
 
	border-bottom: none !important;
 
	margin: 10px 0 !important;
 
    font-size: 1.8em;
 
    font-weight: 700;
 
    border-bottom: none !important;
 
    margin: 10px 0 !important;
 
}
 

	
 
#files_data dl dt {
 
	float: left;
 
	width: 60px;
 
	margin: 0 !important;
 
	padding: 5px;
 
    float: left;
 
    width: 60px;
 
    margin: 0 !important;
 
    padding: 5px;
 
}
 

	
 
#files_data dl dd {
 
	margin: 0 !important;
 
	padding: 5px !important;
 
    margin: 0 !important;
 
    padding: 5px !important;
 
}
 

	
 
.file_history{
 
	padding-top:10px;
 
	font-size:16px;
 
    padding-top:10px;
 
    font-size:16px;
 
}
 
.file_author{
 
	float: left;
 
    float: left;
 
}
 

	
 
.file_author .item{
 
	float:left;
 
	padding:5px;
 
	color: #888;
 
    float:left;
 
    padding:5px;
 
    color: #888;
 
}
 

	
 
.tablerow0 {
 
	background-color: #F8F8F8;
 
    background-color: #F8F8F8;
 
}
 

	
 
.tablerow1 {
 
    background-color: #FFFFFF;
 
}
 

	
 
.changeset_id {
 
	font-family: monospace;
 
	color: #666666;
 
    font-family: monospace;
 
    color: #666666;
 
}
 

	
 
.changeset_hash {
 
	color: #000000;
 
    color: #000000;
 
}
 

	
 
#changeset_content {
 
	border-left: 1px solid #CCC;
 
	border-right: 1px solid #CCC;
 
	border-bottom: 1px solid #CCC;
 
	padding: 5px;
 
    border-left: 1px solid #CCC;
 
    border-right: 1px solid #CCC;
 
    border-bottom: 1px solid #CCC;
 
    padding: 5px;
 
}
 

	
 
#changeset_compare_view_content {
 
	border: 1px solid #CCC;
 
	padding: 5px;
 
    border: 1px solid #CCC;
 
    padding: 5px;
 
}
 

	
 
#changeset_content .container {
 
	min-height: 100px;
 
	font-size: 1.2em;
 
	overflow: hidden;
 
    min-height: 100px;
 
    font-size: 1.2em;
 
    overflow: hidden;
 
}
 

	
 
#changeset_compare_view_content .compare_view_commits {
 
	width: auto !important;
 
    width: auto !important;
 
}
 

	
 
#changeset_compare_view_content .compare_view_commits td {
 
	padding: 0px 0px 0px 12px !important;
 
    padding: 0px 0px 0px 12px !important;
 
}
 

	
 
#changeset_content .container .right {
 
	float: right;
 
	width: 20%;
 
	text-align: right;
 
    float: right;
 
    width: 20%;
 
    text-align: right;
 
}
 

	
 
#changeset_content .container .left .message {
 
	white-space: pre-wrap;
 
    white-space: pre-wrap;
 
}
 
#changeset_content .container .left .message a:hover {
 
	text-decoration: none;
 
    text-decoration: none;
 
}
 
.cs_files .cur_cs {
 
	margin: 10px 2px;
 
	font-weight: bold;
 
    margin: 10px 2px;
 
    font-weight: bold;
 
}
 

	
 
.cs_files .node {
 
	float: left;
 
    float: left;
 
}
 

	
 
.cs_files .changes {
 
	float: right;
 
	color:#003367;
 
	
 
    float: right;
 
    color:#003367;
 
}
 

	
 
.cs_files .changes .added {
 
	background-color: #BBFFBB;
 
	float: left;
 
	text-align: center;
 
	font-size: 9px;
 
    background-color: #BBFFBB;
 
    float: left;
 
    text-align: center;
 
    font-size: 9px;
 
    padding: 2px 0px 2px 0px;
 
}
 

	
 
.cs_files .changes .deleted {
 
	background-color: #FF8888;
 
	float: left;
 
	text-align: center;
 
	font-size: 9px;
 
    background-color: #FF8888;
 
    float: left;
 
    text-align: center;
 
    font-size: 9px;
 
    padding: 2px 0px 2px 0px;
 
}
 
/*new binary*/
 
.cs_files .changes .bin1 {
 
    background-color: #BBFFBB;
 
    float: left;
 
    text-align: center;
 
    font-size: 9px;
 
    padding: 2px 0px 2px 0px;
 
}
 

	
 
/*deleted binary*/
 
.cs_files .changes .bin2 {
 
    background-color: #FF8888;
 
    float: left;
 
    text-align: center;
 
    font-size: 9px;
 
    padding: 2px 0px 2px 0px;
 
}
 

	
 
/*mod binary*/
 
.cs_files .changes .bin3 {
 
    background-color: #DDDDDD;
 
    float: left;
 
    text-align: center;
 
    font-size: 9px;
 
    padding: 2px 0px 2px 0px;
 
}
 

	
 
/*rename file*/
 
.cs_files .changes .bin4 {
 
    background-color: #6D99FF;
 
    float: left;
 
    text-align: center;
 
    font-size: 9px;
 
    padding: 2px 0px 2px 0px;
 
}
 

	
 

	
 
.cs_files .cs_added,.cs_files .cs_A {
 
	background: url("../images/icons/page_white_add.png") no-repeat scroll
 
		3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	margin-top: 7px;
 
	text-align: left;
 
    background: url("../images/icons/page_white_add.png") no-repeat scroll
 
        3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    margin-top: 7px;
 
    text-align: left;
 
}
 

	
 
.cs_files .cs_changed,.cs_files .cs_M {
 
	background: url("../images/icons/page_white_edit.png") no-repeat scroll
 
		3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	margin-top: 7px;
 
	text-align: left;
 
    background: url("../images/icons/page_white_edit.png") no-repeat scroll
 
        3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    margin-top: 7px;
 
    text-align: left;
 
}
 

	
 
.cs_files .cs_removed,.cs_files .cs_D {
 
	background: url("../images/icons/page_white_delete.png") no-repeat
 
		scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	margin-top: 7px;
 
	text-align: left;
 
    background: url("../images/icons/page_white_delete.png") no-repeat
 
        scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    margin-top: 7px;
 
    text-align: left;
 
}
 

	
 
#graph {
 
	overflow: hidden;
 
    overflow: hidden;
 
}
 

	
 
#graph_nodes {
 
	float: left;
 
	margin-right: 0px;
 
	margin-top: 0px;
 
    float: left;
 
    margin-right: 0px;
 
    margin-top: 0px;
 
}
 

	
 
#graph_content {
 
	width: 80%;
 
	float: left;
 
    width: 80%;
 
    float: left;
 
}
 

	
 
#graph_content .container_header {
 
	border-bottom: 1px solid #DDD;
 
	padding: 10px;
 
	height: 25px;
 
    border-bottom: 1px solid #DDD;
 
    padding: 10px;
 
    height: 25px;
 
}
 

	
 
#graph_content #rev_range_container {
 
	float: left;
 
	margin: 0px 0px 0px 3px;
 
    float: left;
 
    margin: 0px 0px 0px 3px;
 
}
 

	
 
#graph_content #rev_range_clear {
 
    float: left;
 
    margin: 0px 0px 0px 3px;
 
}
 

	
 
#graph_content .container {
 
	border-bottom: 1px solid #DDD;
 
	height: 56px;
 
	overflow: hidden;
 
    border-bottom: 1px solid #DDD;
 
    height: 56px;
 
    overflow: hidden;
 
}
 

	
 
#graph_content .container .right {
 
	float: right;
 
	width: 23%;
 
	text-align: right;
 
    float: right;
 
    width: 23%;
 
    text-align: right;
 
}
 

	
 
#graph_content .container .left {
 
	float: left;
 
	width: 25%;
 
	padding-left: 5px;
 
    float: left;
 
    width: 25%;
 
    padding-left: 5px;
 
}
 

	
 
#graph_content .container .mid {
 
	float: left;
 
	width: 49%;
 
    float: left;
 
    width: 49%;
 
}
 

	
 

	
 
#graph_content .container .left .date {
 
	color: #666;
 
	padding-left: 22px;
 
	font-size: 10px;
 
    color: #666;
 
    padding-left: 22px;
 
    font-size: 10px;
 
}
 

	
 
#graph_content .container .left .author {
 
	height: 22px;
 
    height: 22px;
 
}
 

	
 
#graph_content .container .left .author .user {
 
	color: #444444;
 
	float: left;
 
	margin-left: -4px;
 
	margin-top: 4px;
 
    color: #444444;
 
    float: left;
 
    margin-left: -4px;
 
    margin-top: 4px;
 
}
 

	
 
#graph_content .container .mid .message {
 
	white-space: pre-wrap;
 
    white-space: pre-wrap;
 
}
 

	
 
#graph_content .container .mid .message a:hover{
 
	text-decoration: none;
 
    text-decoration: none;
 
}
 

	
 
.revision-link
 
 {
 
	color:#3F6F9F;
 
    color:#3F6F9F;
 
    font-weight: bold !important;
 
}
 

	
 
.issue-tracker-link{
 
    color:#3F6F9F;
 
    font-weight: bold !important;
 
}
 

	
 
.changeset-status-container{
 
    padding-right: 5px;
 
    margin-top:1px;
 
    float:right;
 
    height:14px;
 
}
 
.code-header .changeset-status-container{
 
	float:left;
 
	padding:2px 0px 0px 2px;
 
    float:left;
 
    padding:2px 0px 0px 2px;
 
}
 
.changeset-status-container .changeset-status-lbl{
 
	color: rgb(136, 136, 136);
 
    color: rgb(136, 136, 136);
 
    float: left;
 
    padding: 3px 4px 0px 0px
 
}
 
.code-header .changeset-status-container .changeset-status-lbl{
 
    float: left;
 
    padding: 0px 4px 0px 0px;   
 
    padding: 0px 4px 0px 0px;
 
}
 
.changeset-status-container .changeset-status-ico{
 
    float: left;
 
}
 
.code-header .changeset-status-container .changeset-status-ico, .container .changeset-status-ico{
 
    float: left;
 
}
 
.right .comments-container{
 
	padding-right: 5px;
 
	margin-top:1px;
 
	float:right;
 
	height:14px;
 
    padding-right: 5px;
 
    margin-top:1px;
 
    float:right;
 
    height:14px;
 
}
 

	
 
.right .comments-cnt{
 
    float: left;
 
    color: rgb(136, 136, 136); 
 
    padding-right: 2px; 
 
    color: rgb(136, 136, 136);
 
    padding-right: 2px;
 
}
 

	
 
.right .changes{
 
	clear: both;
 
    clear: both;
 
}
 

	
 
.right .changes .changed_total {
 
	display: block;
 
	float: right;
 
	text-align: center;
 
	min-width: 45px;
 
	cursor: pointer;
 
	color: #444444;
 
	background: #FEA;
 
	-webkit-border-radius: 0px 0px 0px 6px;
 
	-moz-border-radius: 0px 0px 0px 6px;
 
	border-radius: 0px 0px 0px 6px;
 
	padding: 1px;
 
    display: block;
 
    float: right;
 
    text-align: center;
 
    min-width: 45px;
 
    cursor: pointer;
 
    color: #444444;
 
    background: #FEA;
 
    -webkit-border-radius: 0px 0px 0px 6px;
 
    -moz-border-radius: 0px 0px 0px 6px;
 
    border-radius: 0px 0px 0px 6px;
 
    padding: 1px;
 
}
 

	
 
.right .changes .added,.changed,.removed {
 
	display: block;
 
	padding: 1px;
 
	color: #444444;
 
	float: right;
 
	text-align: center;
 
	min-width: 15px;
 
    display: block;
 
    padding: 1px;
 
    color: #444444;
 
    float: right;
 
    text-align: center;
 
    min-width: 15px;
 
}
 

	
 
.right .changes .added {
 
	background: #CFC;
 
    background: #CFC;
 
}
 

	
 
.right .changes .changed {
 
	background: #FEA;
 
    background: #FEA;
 
}
 

	
 
.right .changes .removed {
 
	background: #FAA;
 
    background: #FAA;
 
}
 

	
 
.right .merge {
 
  padding: 1px 3px 1px 3px;
 
  background-color: #fca062;
 
  font-size: 10px;
 
  font-weight: bold;
 
  color: #ffffff;
 
  text-transform: uppercase;
 
  white-space: nowrap;
 
  -webkit-border-radius: 3px;
 
  -moz-border-radius: 3px;
 
  border-radius: 3px;
 
  margin-right: 2px;
 
}
 

	
 
.right .parent {
 
	color: #666666;
 
	clear:both;
 
    color: #666666;
 
    clear:both;
 
}
 
.right .logtags{
 
	padding: 2px 2px 2px 2px;
 
    padding: 2px 2px 2px 2px;
 
}
 
.right .logtags .branchtag,.right .logtags .tagtag,.right .logtags .booktag{
 
    margin: 0px 2px;
 
}
 

	
 
.right .logtags .branchtag,
 
.logtags .branchtag,
 
.spantag {
 
  padding: 1px 3px 1px 3px;
 
  background-color: #bfbfbf;
 
  font-size: 10px;
 
  font-weight: bold;
 
  color: #ffffff;
 
  white-space: nowrap;
 
  -webkit-border-radius: 3px;
 
  -moz-border-radius: 3px;
 
  border-radius: 3px;
 
}
 
.right .logtags .branchtag a:hover,.logtags .branchtag a{
 
	color: #ffffff;
 
    color: #ffffff;
 
}
 
.right .logtags .branchtag a:hover,.logtags .branchtag a:hover{
 
	text-decoration: none;
 
	color: #ffffff;
 
    text-decoration: none;
 
    color: #ffffff;
 
}
 
.right .logtags .tagtag,.logtags .tagtag {
 
  padding: 1px 3px 1px 3px;
 
  background-color: #62cffc;
 
  font-size: 10px;
 
  font-weight: bold;
 
  color: #ffffff;
 
  white-space: nowrap;
 
  -webkit-border-radius: 3px;
 
  -moz-border-radius: 3px;
 
  border-radius: 3px;
 
}
 
.right .logtags .tagtag a:hover,.logtags .tagtag a{
 
	color: #ffffff;
 
    color: #ffffff;
 
}
 
.right .logtags .tagtag a:hover,.logtags .tagtag a:hover{
 
    text-decoration: none;
 
    color: #ffffff;
 
}
 
.right .logbooks .bookbook,.logbooks .bookbook,.right .logtags .bookbook,.logtags .bookbook {
 
  padding: 1px 3px 1px 3px;
 
  background-color: #46A546;
 
  font-size: 10px;
 
  font-weight: bold;
 
  color: #ffffff;
 
  text-transform: uppercase;
 
  white-space: nowrap;
 
  -webkit-border-radius: 3px;
 
  -moz-border-radius: 3px;
 
  border-radius: 3px;
 
}
 
.right .logbooks .bookbook,.logbooks .bookbook a,.right .logtags .bookbook,.logtags .bookbook a{
 
	color: #ffffff;
 
    color: #ffffff;
 
}
 
.right .logbooks .bookbook,.logbooks .bookbook a:hover,.right .logtags .bookbook,.logtags .bookbook a:hover{
 
    text-decoration: none;
 
    color: #ffffff;
 
}
 
div.browserblock {
 
	overflow: hidden;
 
	border: 1px solid #ccc;
 
	background: #f8f8f8;
 
	font-size: 100%;
 
	line-height: 125%;
 
	padding: 0;
 
    overflow: hidden;
 
    border: 1px solid #ccc;
 
    background: #f8f8f8;
 
    font-size: 100%;
 
    line-height: 125%;
 
    padding: 0;
 
    -webkit-border-radius: 6px 6px 0px 0px;
 
    -moz-border-radius: 6px 6px 0px 0px;
 
    border-radius: 6px 6px 0px 0px;	
 
    border-radius: 6px 6px 0px 0px;
 
}
 

	
 
div.browserblock .browser-header {
 
	background: #FFF;
 
	padding: 10px 0px 15px 0px;
 
	width: 100%;
 
    background: #FFF;
 
    padding: 10px 0px 15px 0px;
 
    width: 100%;
 
}
 

	
 
div.browserblock .browser-nav {
 
	float: left
 
    float: left
 
}
 

	
 
div.browserblock .browser-branch {
 
	float: left;
 
    float: left;
 
}
 

	
 
div.browserblock .browser-branch label {
 
	color: #4A4A4A;
 
	vertical-align: text-top;
 
    color: #4A4A4A;
 
    vertical-align: text-top;
 
}
 

	
 
div.browserblock .browser-header span {
 
	margin-left: 5px;
 
	font-weight: 700;
 
    margin-left: 5px;
 
    font-weight: 700;
 
}
 

	
 
div.browserblock .browser-search {
 
	clear: both;
 
	padding: 8px 8px 0px 5px;
 
	height: 20px;
 
    clear: both;
 
    padding: 8px 8px 0px 5px;
 
    height: 20px;
 
}
 

	
 
div.browserblock #node_filter_box {
 
	
 
}
 

	
 
div.browserblock .search_activate {
 
	float: left
 
    float: left
 
}
 

	
 
div.browserblock .add_node {
 
	float: left;
 
	padding-left: 5px;
 
    float: left;
 
    padding-left: 5px;
 
}
 

	
 
div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover
 
	{
 
	text-decoration: none !important;
 
    {
 
    text-decoration: none !important;
 
}
 

	
 
div.browserblock .browser-body {
 
	background: #EEE;
 
	border-top: 1px solid #CCC;
 
    background: #EEE;
 
    border-top: 1px solid #CCC;
 
}
 

	
 
table.code-browser {
 
	border-collapse: collapse;
 
	width: 100%;
 
    border-collapse: collapse;
 
    width: 100%;
 
}
 

	
 
table.code-browser tr {
 
	margin: 3px;
 
    margin: 3px;
 
}
 

	
 
table.code-browser thead th {
 
	background-color: #EEE;
 
	height: 20px;
 
	font-size: 1.1em;
 
	font-weight: 700;
 
	text-align: left;
 
	padding-left: 10px;
 
    background-color: #EEE;
 
    height: 20px;
 
    font-size: 1.1em;
 
    font-weight: 700;
 
    text-align: left;
 
    padding-left: 10px;
 
}
 

	
 
table.code-browser tbody td {
 
	padding-left: 10px;
 
	height: 20px;
 
    padding-left: 10px;
 
    height: 20px;
 
}
 

	
 
table.code-browser .browser-file {
 
	background: url("../images/icons/document_16.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	text-align: left;
 
    background: url("../images/icons/document_16.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    text-align: left;
 
}
 
.diffblock .changeset_header {
 
    height: 16px;
 
}
 
.diffblock .changeset_file {
 
	background: url("../images/icons/file.png") no-repeat scroll 3px;
 
	text-align: left;
 
	float: left;
 
	padding: 2px 0px 2px 22px;
 
    background: url("../images/icons/file.png") no-repeat scroll 3px;
 
    text-align: left;
 
    float: left;
 
    padding: 2px 0px 2px 22px;
 
}
 
.diffblock .diff-menu-wrapper{
 
	float: left;
 
    float: left;
 
}
 

	
 
.diffblock .diff-menu{
 
    position: absolute;
 
    background: none repeat scroll 0 0 #FFFFFF;
 
    border-color: #003367 #666666 #666666;
 
    border-right: 1px solid #666666;
 
    border-style: solid solid solid;
 
    border-width: 1px;
 
    box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
 
    margin-top:5px;
 
    margin-left:1px;
 
    
 

	
 
}
 
.diffblock .diff-actions {
 
    padding: 2px 0px 0px 2px;
 
    float: left;
 
}
 
.diffblock  .diff-menu ul li {
 
	padding: 0px 0px 0px 0px !important;
 
    padding: 0px 0px 0px 0px !important;
 
}
 
.diffblock  .diff-menu ul li a{
 
	display: block;
 
	padding: 3px 8px 3px 8px !important;
 
    display: block;
 
    padding: 3px 8px 3px 8px !important;
 
}
 
.diffblock  .diff-menu ul li a:hover{
 
    text-decoration: none;
 
    background-color: #EEEEEE;
 
}
 
table.code-browser .browser-dir {
 
	background: url("../images/icons/folder_16.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	text-align: left;
 
    background: url("../images/icons/folder_16.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    text-align: left;
 
}
 

	
 
table.code-browser .submodule-dir {
 
    background: url("../images/icons/disconnect.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    text-align: left;
 
}
 

	
 

	
 
.box .search {
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0;
 
	padding: 0 20px 10px;
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0;
 
    padding: 0 20px 10px;
 
}
 

	
 
.box .search div.search_path {
 
	background: none repeat scroll 0 0 #EEE;
 
	border: 1px solid #CCC;
 
	color: blue;
 
	margin-bottom: 10px;
 
	padding: 10px 0;
 
    background: none repeat scroll 0 0 #EEE;
 
    border: 1px solid #CCC;
 
    color: blue;
 
    margin-bottom: 10px;
 
    padding: 10px 0;
 
}
 

	
 
.box .search div.search_path div.link {
 
	font-weight: 700;
 
	margin-left: 25px;
 
    font-weight: 700;
 
    margin-left: 25px;
 
}
 

	
 
.box .search div.search_path div.link a {
 
	color: #003367;
 
	cursor: pointer;
 
	text-decoration: none;
 
    color: #003367;
 
    cursor: pointer;
 
    text-decoration: none;
 
}
 

	
 
#path_unlock {
 
	color: red;
 
	font-size: 1.2em;
 
	padding-left: 4px;
 
    color: red;
 
    font-size: 1.2em;
 
    padding-left: 4px;
 
}
 

	
 
.info_box span {
 
	margin-left: 3px;
 
	margin-right: 3px;
 
    margin-left: 3px;
 
    margin-right: 3px;
 
}
 

	
 
.info_box .rev {
 
	color: #003367;
 
	font-size: 1.6em;
 
	font-weight: bold;
 
	vertical-align: sub;
 
    color: #003367;
 
    font-size: 1.6em;
 
    font-weight: bold;
 
    vertical-align: sub;
 
}
 

	
 
.info_box input#at_rev,.info_box input#size {
 
	background: #FFF;
 
	border-top: 1px solid #b3b3b3;
 
	border-left: 1px solid #b3b3b3;
 
	border-right: 1px solid #eaeaea;
 
	border-bottom: 1px solid #eaeaea;
 
	color: #000;
 
	font-size: 12px;
 
	margin: 0;
 
	padding: 1px 5px 1px;
 
    background: #FFF;
 
    border-top: 1px solid #b3b3b3;
 
    border-left: 1px solid #b3b3b3;
 
    border-right: 1px solid #eaeaea;
 
    border-bottom: 1px solid #eaeaea;
 
    color: #000;
 
    font-size: 12px;
 
    margin: 0;
 
    padding: 1px 5px 1px;
 
}
 

	
 
.info_box input#view {
 
	text-align: center;
 
	padding: 4px 3px 2px 2px;
 
    text-align: center;
 
    padding: 4px 3px 2px 2px;
 
}
 

	
 
.yui-overlay,.yui-panel-container {
 
	visibility: hidden;
 
	position: absolute;
 
	z-index: 2;
 
    visibility: hidden;
 
    position: absolute;
 
    z-index: 2;
 
}
 

	
 
#tip-box {
 
	position: absolute;
 
	
 
	background-color: #FFF;
 
	border: 2px solid #003367;
 
	font: 100% sans-serif;
 
	width: auto;
 
	opacity: 1px;
 
	padding: 8px;
 
	
 
	white-space: pre-wrap;
 
	-webkit-border-radius: 8px 8px 8px 8px;
 
	-khtml-border-radius: 8px 8px 8px 8px;
 
	-moz-border-radius: 8px 8px 8px 8px;
 
	border-radius: 8px 8px 8px 8px;
 
	box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
	-moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
	-webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    position: absolute;
 

	
 
    background-color: #FFF;
 
    border: 2px solid #003367;
 
    font: 100% sans-serif;
 
    width: auto;
 
    opacity: 1px;
 
    padding: 8px;
 

	
 
    white-space: pre-wrap;
 
    -webkit-border-radius: 8px 8px 8px 8px;
 
    -khtml-border-radius: 8px 8px 8px 8px;
 
    -moz-border-radius: 8px 8px 8px 8px;
 
    border-radius: 8px 8px 8px 8px;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    -moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
}
 

	
 
.hl-tip-box {
 
    visibility: hidden;
 
    position: absolute;
 
    color: #666;
 
    background-color: #FFF;
 
    border: 2px solid #003367;
 
    font: 100% sans-serif;
 
    width: auto;
 
    opacity: 1px;
 
    padding: 8px;
 
    white-space: pre-wrap;
 
    -webkit-border-radius: 8px 8px 8px 8px;
 
    -khtml-border-radius: 8px 8px 8px 8px;
 
    -moz-border-radius: 8px 8px 8px 8px;
 
    border-radius: 8px 8px 8px 8px;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
}
 

	
 

	
 
.mentions-container{
 
	width: 90% !important;
 
    width: 90% !important;
 
}
 
.mentions-container .yui-ac-content{
 
	width: 100% !important;
 
    width: 100% !important;
 
}
 

	
 
.ac {
 
	vertical-align: top;
 
    vertical-align: top;
 
}
 

	
 
.ac .yui-ac {
 
	position: inherit;
 
	font-size: 100%;
 
    position: inherit;
 
    font-size: 100%;
 
}
 

	
 
.ac .perm_ac {
 
	width: 20em;
 
    width: 20em;
 
}
 

	
 
.ac .yui-ac-input {
 
	width: 100%;
 
    width: 100%;
 
}
 

	
 
.ac .yui-ac-container {
 
	position: absolute;
 
	top: 1.6em;
 
	width: auto;
 
    position: absolute;
 
    top: 1.6em;
 
    width: auto;
 
}
 

	
 
.ac .yui-ac-content {
 
	position: absolute;
 
	border: 1px solid gray;
 
	background: #fff;
 
	z-index: 9050;
 
	
 
    position: absolute;
 
    border: 1px solid gray;
 
    background: #fff;
 
    z-index: 9050;
 
}
 

	
 
.ac .yui-ac-shadow {
 
	position: absolute;
 
	width: 100%;
 
	background: #000;
 
	-moz-opacity: 0.1px;
 
	opacity: .10;
 
	filter: alpha(opacity = 10);
 
	z-index: 9049;
 
	margin: .3em;
 
    position: absolute;
 
    width: 100%;
 
    background: #000;
 
    -moz-opacity: 0.1px;
 
    opacity: .10;
 
    filter: alpha(opacity = 10);
 
    z-index: 9049;
 
    margin: .3em;
 
}
 

	
 
.ac .yui-ac-content ul {
 
	width: 100%;
 
	margin: 0;
 
	padding: 0;
 
	z-index: 9050;
 
    width: 100%;
 
    margin: 0;
 
    padding: 0;
 
    z-index: 9050;
 
}
 

	
 
.ac .yui-ac-content li {
 
	cursor: default;
 
	white-space: nowrap;
 
	margin: 0;
 
	padding: 2px 5px;
 
	height: 18px;
 
	z-index: 9050;
 
	display: block;
 
	width: auto !important;
 
    cursor: default;
 
    white-space: nowrap;
 
    margin: 0;
 
    padding: 2px 5px;
 
    height: 18px;
 
    z-index: 9050;
 
    display: block;
 
    width: auto !important;
 
}
 

	
 
.ac .yui-ac-content li .ac-container-wrap{
 
    width: auto;
 
}
 

	
 
.ac .yui-ac-content li.yui-ac-prehighlight {
 
	background: #B3D4FF;
 
	z-index: 9050;
 
    background: #B3D4FF;
 
    z-index: 9050;
 
}
 

	
 
.ac .yui-ac-content li.yui-ac-highlight {
 
	background: #556CB5;
 
	color: #FFF;
 
	z-index: 9050;
 
    background: #556CB5;
 
    color: #FFF;
 
    z-index: 9050;
 
}
 
.ac .yui-ac-bd{
 
	z-index: 9050;
 
    z-index: 9050;
 
}
 

	
 
.follow {
 
	background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
	height: 16px;
 
	width: 20px;
 
	cursor: pointer;
 
	display: block;
 
	float: right;
 
	margin-top: 2px;
 
    background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
    height: 16px;
 
    width: 20px;
 
    cursor: pointer;
 
    display: block;
 
    float: right;
 
    margin-top: 2px;
 
}
 

	
 
.following {
 
	background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
	height: 16px;
 
	width: 20px;
 
	cursor: pointer;
 
	display: block;
 
	float: right;
 
	margin-top: 2px;
 
    background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
    height: 16px;
 
    width: 20px;
 
    cursor: pointer;
 
    display: block;
 
    float: right;
 
    margin-top: 2px;
 
}
 

	
 
.reposize {
 
    background: url("../images/icons/server.png") no-repeat scroll 3px;
 
    height: 16px;
 
    width: 20px;
 
    cursor: pointer;
 
    display: block;
 
    float: right;
 
    margin-top: 2px;
 
}
 

	
 
#repo_size{
 
	display: block;
 
	margin-top: 4px;
 
	color: #666;
 
	float:right;
 
    display: block;
 
    margin-top: 4px;
 
    color: #666;
 
    float:right;
 
}
 

	
 
.locking_locked{
 
    background: #FFF url("../images/icons/block_16.png") no-repeat scroll 3px;
 
    height: 16px;
 
    width: 20px;
 
    cursor: pointer;
 
    display: block;
 
    float: right;
 
    margin-top: 2px;    
 
    margin-top: 2px;
 
}
 

	
 
.locking_unlocked{
 
    background: #FFF url("../images/icons/accept.png") no-repeat scroll 3px;
 
    height: 16px;
 
    width: 20px;
 
    cursor: pointer;
 
    display: block;
 
    float: right;
 
    margin-top: 2px;	
 
    margin-top: 2px;
 
}
 

	
 
.currently_following {
 
	padding-left: 10px;
 
	padding-bottom: 5px;
 
    padding-left: 10px;
 
    padding-bottom: 5px;
 
}
 

	
 
.add_icon {
 
	background: url("../images/icons/add.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
    background: url("../images/icons/add.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
.accept_icon {
 
    background: url("../images/icons/accept.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
.edit_icon {
 
	background: url("../images/icons/application_form_edit.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
    background: url("../images/icons/application_form_edit.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
.delete_icon {
 
	background: url("../images/icons/delete.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
    background: url("../images/icons/delete.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
.refresh_icon {
 
	background: url("../images/icons/arrow_refresh.png") no-repeat scroll
 
		3px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
    background: url("../images/icons/arrow_refresh.png") no-repeat scroll
 
        3px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
.pull_icon {
 
	background: url("../images/icons/connect.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
    background: url("../images/icons/connect.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
}
 

	
 
.rss_icon {
 
	background: url("../images/icons/rss_16.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	padding-top: 4px;
 
	text-align: left;
 
	font-size: 8px
 
    background: url("../images/icons/rss_16.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 4px;
 
    text-align: left;
 
    font-size: 8px
 
}
 

	
 
.atom_icon {
 
	background: url("../images/icons/atom.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	padding-top: 4px;
 
	text-align: left;
 
	font-size: 8px
 
    background: url("../images/icons/atom.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    padding-top: 4px;
 
    text-align: left;
 
    font-size: 8px
 
}
 

	
 
.archive_icon {
 
	background: url("../images/icons/compress.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	text-align: left;
 
	padding-top: 1px;
 
    background: url("../images/icons/compress.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    text-align: left;
 
    padding-top: 1px;
 
}
 

	
 
.start_following_icon {
 
	background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	text-align: left;
 
	padding-top: 0px;
 
    background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    text-align: left;
 
    padding-top: 0px;
 
}
 

	
 
.stop_following_icon {
 
	background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
	padding-left: 20px;
 
	text-align: left;
 
	padding-top: 0px;
 
    background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
    padding-left: 20px;
 
    text-align: left;
 
    padding-top: 0px;
 
}
 

	
 
.action_button {
 
	border: 0;
 
	display: inline;
 
    border: 0;
 
    display: inline;
 
}
 

	
 
.action_button:hover {
 
	border: 0;
 
	text-decoration: underline;
 
	cursor: pointer;
 
    border: 0;
 
    text-decoration: underline;
 
    cursor: pointer;
 
}
 

	
 
#switch_repos {
 
	position: absolute;
 
	height: 25px;
 
	z-index: 1;
 
    position: absolute;
 
    height: 25px;
 
    z-index: 1;
 
}
 

	
 
#switch_repos select {
 
	min-width: 150px;
 
	max-height: 250px;
 
	z-index: 1;
 
    min-width: 150px;
 
    max-height: 250px;
 
    z-index: 1;
 
}
 

	
 
.breadcrumbs {
 
	border: medium none;
 
	color: #FFF;
 
	float: left;
 
	font-weight: 700;
 
	font-size: 14px;
 
	margin: 0;
 
	padding: 11px 0 11px 10px;
 
    border: medium none;
 
    color: #FFF;
 
    float: left;
 
    font-weight: 700;
 
    font-size: 14px;
 
    margin: 0;
 
    padding: 11px 0 11px 10px;
 
}
 

	
 
.breadcrumbs .hash {
 
	text-transform: none;
 
	color: #fff;
 
    text-transform: none;
 
    color: #fff;
 
}
 

	
 
.breadcrumbs a {
 
	color: #FFF;
 
    color: #FFF;
 
}
 

	
 
.flash_msg {
 
	
 
}
 

	
 
.flash_msg ul {
 
	
 
}
 

	
 
.error_red {
 
	color:red;
 
    color:red;
 
}
 

	
 
.error_msg {
 
	background-color: #c43c35;
 
	background-repeat: repeat-x;
 
	background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35) );
 
	background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
 
	background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) );
 
	background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
 
	background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
 
	background-image: linear-gradient(top, #ee5f5b, #c43c35);
 
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 );
 
	border-color: #c43c35 #c43c35 #882a25;
 
    background-color: #c43c35;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35) );
 
    background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
 
    background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) );
 
    background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
 
    background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
 
    background-image: linear-gradient(top, #ee5f5b, #c43c35);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 );
 
    border-color: #c43c35 #c43c35 #882a25;
 
}
 

	
 
.warning_msg {
 
	color: #404040 !important;
 
	background-color: #eedc94;
 
	background-repeat: repeat-x;
 
	background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94) );
 
	background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
 
	background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) );
 
	background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
 
	background-image: -o-linear-gradient(top, #fceec1, #eedc94);
 
	background-image: linear-gradient(top, #fceec1, #eedc94);
 
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 );
 
	border-color: #eedc94 #eedc94 #e4c652;
 
    color: #404040 !important;
 
    background-color: #eedc94;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94) );
 
    background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
 
    background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) );
 
    background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
 
    background-image: -o-linear-gradient(top, #fceec1, #eedc94);
 
    background-image: linear-gradient(top, #fceec1, #eedc94);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 );
 
    border-color: #eedc94 #eedc94 #e4c652;
 
}
 

	
 
.success_msg {
 
	background-color: #57a957;
 
	background-repeat: repeat-x !important;
 
	background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957) );
 
	background-image: -moz-linear-gradient(top, #62c462, #57a957);
 
	background-image: -ms-linear-gradient(top, #62c462, #57a957);
 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) );
 
	background-image: -webkit-linear-gradient(top, #62c462, #57a957);
 
	background-image: -o-linear-gradient(top, #62c462, #57a957);
 
	background-image: linear-gradient(top, #62c462, #57a957);
 
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 );
 
	border-color: #57a957 #57a957 #3d773d;
 
    background-color: #57a957;
 
    background-repeat: repeat-x !important;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957) );
 
    background-image: -moz-linear-gradient(top, #62c462, #57a957);
 
    background-image: -ms-linear-gradient(top, #62c462, #57a957);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) );
 
    background-image: -webkit-linear-gradient(top, #62c462, #57a957);
 
    background-image: -o-linear-gradient(top, #62c462, #57a957);
 
    background-image: linear-gradient(top, #62c462, #57a957);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 );
 
    border-color: #57a957 #57a957 #3d773d;
 
}
 

	
 
.notice_msg {
 
	background-color: #339bb9;
 
	background-repeat: repeat-x;
 
	background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9) );
 
	background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
 
	background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
 
	background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) );
 
	background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
 
	background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
 
	background-image: linear-gradient(top, #5bc0de, #339bb9);
 
	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 );
 
	border-color: #339bb9 #339bb9 #22697d;
 
    background-color: #339bb9;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9) );
 
    background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
 
    background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) );
 
    background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
 
    background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
 
    background-image: linear-gradient(top, #5bc0de, #339bb9);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 );
 
    border-color: #339bb9 #339bb9 #22697d;
 
}
 

	
 
.success_msg,.error_msg,.notice_msg,.warning_msg {
 
	font-size: 12px;
 
	font-weight: 700;
 
	min-height: 14px;
 
	line-height: 14px;
 
	margin-bottom: 10px;
 
	margin-top: 0;
 
	display: block;
 
	overflow: auto;
 
	padding: 6px 10px 6px 10px;
 
	border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
	position: relative;
 
	color: #FFF;
 
	border-width: 1px;
 
	border-style: solid;
 
	-webkit-border-radius: 4px;
 
	-moz-border-radius: 4px;
 
	border-radius: 4px;
 
	-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
 
	-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
 
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
 
    font-size: 12px;
 
    font-weight: 700;
 
    min-height: 14px;
 
    line-height: 14px;
 
    margin-bottom: 10px;
 
    margin-top: 0;
 
    display: block;
 
    overflow: auto;
 
    padding: 6px 10px 6px 10px;
 
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
    position: relative;
 
    color: #FFF;
 
    border-width: 1px;
 
    border-style: solid;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;
 
    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
 
    -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
 
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
 
}
 

	
 
#msg_close {
 
	background: transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
 
	cursor: pointer;
 
	height: 16px;
 
	position: absolute;
 
	right: 5px;
 
	top: 5px;
 
	width: 16px;
 
    background: transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
 
    cursor: pointer;
 
    height: 16px;
 
    position: absolute;
 
    right: 5px;
 
    top: 5px;
 
    width: 16px;
 
}
 
div#legend_data{
 
	padding-left:10px;
 
    padding-left:10px;
 
}
 
div#legend_container table{
 
	border: none !important;
 
    border: none !important;
 
}
 
div#legend_container table,div#legend_choices table {
 
	width: auto !important;
 
    width: auto !important;
 
}
 

	
 
table#permissions_manage {
 
	width: 0 !important;
 
    width: 0 !important;
 
}
 

	
 
table#permissions_manage span.private_repo_msg {
 
	font-size: 0.8em;
 
	opacity: 0.6px;
 
    font-size: 0.8em;
 
    opacity: 0.6px;
 
}
 

	
 
table#permissions_manage td.private_repo_msg {
 
	font-size: 0.8em;
 
    font-size: 0.8em;
 
}
 

	
 
table#permissions_manage tr#add_perm_input td {
 
	vertical-align: middle;
 
    vertical-align: middle;
 
}
 

	
 
div.gravatar {
 
	background-color: #FFF;
 
	float: left;
 
	margin-right: 0.7em;
 
	padding: 1px 1px 1px 1px;
 
    background-color: #FFF;
 
    float: left;
 
    margin-right: 0.7em;
 
    padding: 1px 1px 1px 1px;
 
    line-height:0;
 
	-webkit-border-radius: 3px;
 
	-khtml-border-radius: 3px;
 
	-moz-border-radius: 3px;
 
	border-radius: 3px;
 
    -webkit-border-radius: 3px;
 
    -khtml-border-radius: 3px;
 
    -moz-border-radius: 3px;
 
    border-radius: 3px;
 
}
 

	
 
div.gravatar img {
 
	-webkit-border-radius: 2px;
 
	-khtml-border-radius: 2px;
 
	-moz-border-radius: 2px;
 
	border-radius: 2px;
 
    -webkit-border-radius: 2px;
 
    -khtml-border-radius: 2px;
 
    -moz-border-radius: 2px;
 
    border-radius: 2px;
 
}
 

	
 
#header,#content,#footer {
 
	min-width: 978px;
 
    min-width: 978px;
 
}
 

	
 
#content {
 
	clear: both;
 
	overflow: hidden;
 
	padding: 54px 10px 14px 10px;
 
    clear: both;
 
    overflow: hidden;
 
    padding: 54px 10px 14px 10px;
 
}
 

	
 
#content div.box div.title div.search {
 
	
 
	border-left: 1px solid #316293;
 
    border-left: 1px solid #316293;
 
}
 

	
 
#content div.box div.title div.search div.input input {
 
	border: 1px solid #316293;
 
    border: 1px solid #316293;
 
}
 

	
 
.ui-btn{
 
    color: #515151;
 
    background-color: #DADADA;
 
    background-repeat: repeat-x;
 
    background-image: -khtml-gradient(linear, left top, left bottom, from(#F4F4F4),to(#DADADA) );
 
    background-image: -moz-linear-gradient(top, #F4F4F4, #DADADA);
 
    background-image: -ms-linear-gradient(top, #F4F4F4, #DADADA);
 
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F4F4F4),color-stop(100%, #DADADA) );
 
    background-image: -webkit-linear-gradient(top, #F4F4F4, #DADADA) );
 
    background-image: -o-linear-gradient(top, #F4F4F4, #DADADA) );
 
    background-image: linear-gradient(top, #F4F4F4, #DADADA);
 
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F4F4F4', endColorstr='#DADADA', GradientType=0);
 
    
 

	
 
    border-top: 1px solid #DDD;
 
    border-left: 1px solid #c6c6c6;
 
    border-right: 1px solid #DDD;
 
    border-bottom: 1px solid #c6c6c6;
 
    color: #515151;
 
    outline: none;
 
    margin: 0px 3px 3px 0px;
 
    -webkit-border-radius: 4px 4px 4px 4px !important;
 
    -khtml-border-radius: 4px 4px 4px 4px !important;
 
    -moz-border-radius: 4px 4px 4px 4px !important;
 
    border-radius: 4px 4px 4px 4px !important;
 
    cursor: pointer !important;
 
	padding: 3px 3px 3px 3px;	
 
	background-position: 0 -15px;
 
    padding: 3px 3px 3px 3px;
 
    background-position: 0 -15px;
 

	
 
}
 

	
 
.ui-btn.disabled{
 
	color: #999;
 
    color: #999;
 
}
 

	
 
.ui-btn.xsmall{
 
    padding: 1px 2px 1px 1px;
 
}
 

	
 
.ui-btn.large{
 
	padding: 6px 12px;
 
    padding: 6px 12px;
 
}
 

	
 
.ui-btn.clone{
 
	padding: 5px 2px 6px 1px;
 
	margin: 0px -4px 3px 0px;
 
    padding: 5px 2px 6px 1px;
 
    margin: 0px -4px 3px 0px;
 
    -webkit-border-radius: 4px 0px 0px 4px !important;
 
    -khtml-border-radius: 4px 0px 0px 4px !important;
 
    -moz-border-radius: 4px 0px 0px 4px !important;
 
    border-radius: 4px 0px 0px 4px !important;
 
    width: 100px;
 
    text-align: center;
 
    float: left;
 
    position: absolute;
 
}
 
.ui-btn:focus {
 
  outline: none;
 
}
 
.ui-btn:hover{
 
    background-position: 0 -15px;
 
    text-decoration: none;
 
    color: #515151;
 
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important;
 
}
 

	
 
.ui-btn.disabled:hover{
 
    background-position:none;
 
    color: #999;
 
    text-decoration: none;
 
    box-shadow: none !important;
 
}
 

	
 
.ui-btn.red{
 
  color:#fff;
 
  background-color: #c43c35;
 
  background-repeat: repeat-x;
 
  background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
 
  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
 
  background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
 
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
 
  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
 
  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
 
  background-image: linear-gradient(top, #ee5f5b, #c43c35);
 
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
 
  border-color: #c43c35 #c43c35 #882a25;
 
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
}
 

	
 

	
 
.ui-btn.blue{
 
  color:#fff;
 
  background-color: #339bb9;
 
  background-repeat: repeat-x;
 
  background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));
 
  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
 
  background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
 
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
 
  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
 
  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
 
  background-image: linear-gradient(top, #5bc0de, #339bb9);
 
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
 
  border-color: #339bb9 #339bb9 #22697d;
 
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);    
 
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
}
 

	
 
.ui-btn.green{
 
  background-color: #57a957;
 
  background-repeat: repeat-x;
 
  background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
 
  background-image: -moz-linear-gradient(top, #62c462, #57a957);
 
  background-image: -ms-linear-gradient(top, #62c462, #57a957);
 
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
 
  background-image: -webkit-linear-gradient(top, #62c462, #57a957);
 
  background-image: -o-linear-gradient(top, #62c462, #57a957);
 
  background-image: linear-gradient(top, #62c462, #57a957);
 
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
 
  border-color: #57a957 #57a957 #3d773d;
 
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);	
 
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
}
 

	
 
.ui-btn.blue.hidden{
 
	display: none;
 
    display: none;
 
}
 

	
 
.ui-btn.active{
 
    font-weight: bold;
 
}
 

	
 
ins,div.options a:hover {
 
	text-decoration: none;
 
    text-decoration: none;
 
}
 

	
 
img,
 
#header #header-inner #quick li a:hover span.normal,
 
#header #header-inner #quick li ul li.last,
 
#content div.box div.form div.fields div.field div.textarea table td table td a,
 
#clone_url,
 
#clone_url_id
 
{
 
	border: none;
 
    border: none;
 
}
 

	
 
img.icon,.right .merge img {
 
	vertical-align: bottom;
 
    vertical-align: bottom;
 
}
 

	
 
#header ul#logged-user,#content div.box div.title ul.links,
 
#content div.box div.message div.dismiss,
 
#content div.box div.traffic div.legend ul
 
	{
 
	float: right;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    float: right;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#header #header-inner #home,#header #header-inner #logo,
 
#content div.box ul.left,#content div.box ol.left,
 
#content div.box div.pagination-left,div#commit_history,
 
div#legend_data,div#legend_container,div#legend_choices
 
	{
 
	float: left;
 
    {
 
    float: left;
 
}
 

	
 
#header #header-inner #quick li #quick_login,
 
#header #header-inner #quick li:hover ul ul,
 
#header #header-inner #quick li:hover ul ul ul,
 
#header #header-inner #quick li:hover ul ul ul ul,
 
#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow
 
	{
 
	display: none;
 
    {
 
    display: none;
 
}
 

	
 
#header #header-inner #quick li:hover #quick_login,
 
#header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded
 
	{
 
	display: block;
 
    {
 
    display: block;
 
}
 

	
 
#content div.graph {
 
	padding: 0 10px 10px;
 
    padding: 0 10px 10px;
 
}
 

	
 
#content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a
 
	{
 
	color: #bfe3ff;
 
    {
 
    color: #bfe3ff;
 
}
 

	
 
#content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal
 
	{
 
	margin: 10px 24px 10px 44px;
 
    {
 
    margin: 10px 24px 10px 44px;
 
}
 

	
 
#content div.box div.form,#content div.box div.table,#content div.box div.traffic
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0;
 
	padding: 0 20px 10px;
 
    {
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0;
 
    padding: 0 20px 10px;
 
}
 

	
 
#content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span
 
	{
 
	height: 1%;
 
	display: block;
 
	color: #363636;
 
	margin: 0;
 
	padding: 2px 0 0;
 
    {
 
    height: 1%;
 
    display: block;
 
    color: #363636;
 
    margin: 0;
 
    padding: 2px 0 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error
 
	{
 
	background: #FBE3E4;
 
	border-top: 1px solid #e1b2b3;
 
	border-left: 1px solid #e1b2b3;
 
	border-right: 1px solid #FBC2C4;
 
	border-bottom: 1px solid #FBC2C4;
 
    {
 
    background: #FBE3E4;
 
    border-top: 1px solid #e1b2b3;
 
    border-left: 1px solid #e1b2b3;
 
    border-right: 1px solid #FBC2C4;
 
    border-bottom: 1px solid #FBC2C4;
 
}
 

	
 
#content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success
 
	{
 
	background: #E6EFC2;
 
	border-top: 1px solid #cebb98;
 
	border-left: 1px solid #cebb98;
 
	border-right: 1px solid #c6d880;
 
	border-bottom: 1px solid #c6d880;
 
    {
 
    background: #E6EFC2;
 
    border-top: 1px solid #cebb98;
 
    border-left: 1px solid #cebb98;
 
    border-right: 1px solid #c6d880;
 
    border-bottom: 1px solid #c6d880;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input
 
	{
 
	margin: 0;
 
    {
 
    margin: 0;
 
}
 

	
 
#content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios
 
	{
 
	margin: 0 0 0 0px !important;
 
	padding: 0;
 
    {
 
    margin: 0 0 0 0px !important;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios
 
	{
 
	margin: 0 0 0 200px;
 
	padding: 0;
 
    {
 
    margin: 0 0 0 200px;
 
    padding: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover
 
	{
 
	color: #000;
 
	text-decoration: none;
 
    {
 
    color: #000;
 
    text-decoration: none;
 
}
 

	
 
#content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus
 
	{
 
	border: 1px solid #666;
 
    {
 
    border: 1px solid #666;
 
}
 

	
 
#content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0;
 
	padding: 8px 0 2px;
 
    {
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0;
 
    padding: 8px 0 2px;
 
}
 

	
 
#content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input
 
	{
 
	float: left;
 
	margin: 0;
 
    {
 
    float: left;
 
    margin: 0;
 
}
 

	
 
#content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label
 
	{
 
	height: 1%;
 
	display: block;
 
	float: left;
 
	margin: 2px 0 0 4px;
 
    {
 
    height: 1%;
 
    display: block;
 
    float: left;
 
    margin: 2px 0 0 4px;
 
}
 

	
 
div.form div.fields div.field div.button input,
 
#content div.box div.form div.fields div.buttons input
 
div.form div.fields div.buttons input,
 
#content div.box div.action div.button input {
 
	/*color: #000;*/
 
    /*color: #000;*/
 
    font-size: 11px;
 
    font-weight: 700;
 
    margin: 0;
 
}
 

	
 
input.ui-button {
 
	background: #e5e3e3 url("../images/button.png") repeat-x;
 
	border-top: 1px solid #DDD;
 
	border-left: 1px solid #c6c6c6;
 
	border-right: 1px solid #DDD;
 
	border-bottom: 1px solid #c6c6c6;
 
	color: #515151 !important;
 
	outline: none;
 
	margin: 0;
 
	padding: 6px 12px;
 
	-webkit-border-radius: 4px 4px 4px 4px;
 
	-khtml-border-radius: 4px 4px 4px 4px;
 
	-moz-border-radius: 4px 4px 4px 4px;
 
	border-radius: 4px 4px 4px 4px;
 
	box-shadow: 0 1px 0 #ececec;
 
	cursor: pointer;
 
    background: #e5e3e3 url("../images/button.png") repeat-x;
 
    border-top: 1px solid #DDD;
 
    border-left: 1px solid #c6c6c6;
 
    border-right: 1px solid #DDD;
 
    border-bottom: 1px solid #c6c6c6;
 
    color: #515151 !important;
 
    outline: none;
 
    margin: 0;
 
    padding: 6px 12px;
 
    -webkit-border-radius: 4px 4px 4px 4px;
 
    -khtml-border-radius: 4px 4px 4px 4px;
 
    -moz-border-radius: 4px 4px 4px 4px;
 
    border-radius: 4px 4px 4px 4px;
 
    box-shadow: 0 1px 0 #ececec;
 
    cursor: pointer;
 
}
 

	
 
input.ui-button:hover {
 
	background: #b4b4b4 url("../images/button_selected.png") repeat-x;
 
	border-top: 1px solid #ccc;
 
	border-left: 1px solid #bebebe;
 
	border-right: 1px solid #b1b1b1;
 
	border-bottom: 1px solid #afafaf;
 
    background: #b4b4b4 url("../images/button_selected.png") repeat-x;
 
    border-top: 1px solid #ccc;
 
    border-left: 1px solid #bebebe;
 
    border-right: 1px solid #b1b1b1;
 
    border-bottom: 1px solid #afafaf;
 
}
 

	
 
div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight
 
	{
 
	display: inline;
 
    {
 
    display: inline;
 
}
 

	
 
#content div.box div.form div.fields div.buttons,div.form div.fields div.buttons
 
	{
 
	margin: 10px 0 0 200px;
 
	padding: 0;
 
    {
 
    margin: 10px 0 0 200px;
 
    padding: 0;
 
}
 

	
 
#content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons
 
	{
 
	margin: 10px 0 0;
 
    {
 
    margin: 10px 0 0;
 
}
 

	
 
#content div.box table td.user,#content div.box table td.address {
 
	width: 10%;
 
	text-align: center;
 
    width: 10%;
 
    text-align: center;
 
}
 

	
 
#content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link
 
	{
 
	text-align: right;
 
	margin: 6px 0 0;
 
	padding: 0;
 
    {
 
    text-align: right;
 
    margin: 6px 0 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover
 
	{
 
	background: #b4b4b4 url("../images/button_selected.png") repeat-x;
 
	border-top: 1px solid #ccc;
 
	border-left: 1px solid #bebebe;
 
	border-right: 1px solid #b1b1b1;
 
	border-bottom: 1px solid #afafaf;
 
	color: #515151;
 
	margin: 0;
 
	padding: 6px 12px;
 
    {
 
    background: #b4b4b4 url("../images/button_selected.png") repeat-x;
 
    border-top: 1px solid #ccc;
 
    border-left: 1px solid #bebebe;
 
    border-right: 1px solid #b1b1b1;
 
    border-bottom: 1px solid #afafaf;
 
    color: #515151;
 
    margin: 0;
 
    padding: 6px 12px;
 
}
 

	
 
#content div.box div.pagination div.results,#content div.box div.pagination-wh div.results
 
	{
 
	text-align: left;
 
	float: left;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    text-align: left;
 
    float: left;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span
 
	{
 
	height: 1%;
 
	display: block;
 
	float: left;
 
	background: #ebebeb url("../images/pager.png") repeat-x;
 
	border-top: 1px solid #dedede;
 
	border-left: 1px solid #cfcfcf;
 
	border-right: 1px solid #c4c4c4;
 
	border-bottom: 1px solid #c4c4c4;
 
	color: #4A4A4A;
 
	font-weight: 700;
 
	margin: 0;
 
	padding: 6px 8px;
 
    {
 
    height: 1%;
 
    display: block;
 
    float: left;
 
    background: #ebebeb url("../images/pager.png") repeat-x;
 
    border-top: 1px solid #dedede;
 
    border-left: 1px solid #cfcfcf;
 
    border-right: 1px solid #c4c4c4;
 
    border-bottom: 1px solid #c4c4c4;
 
    color: #4A4A4A;
 
    font-weight: 700;
 
    margin: 0;
 
    padding: 6px 8px;
 
}
 

	
 
#content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled
 
	{
 
	color: #B4B4B4;
 
	padding: 6px;
 
    {
 
    color: #B4B4B4;
 
    padding: 6px;
 
}
 

	
 
#login,#register {
 
	width: 520px;
 
	margin: 10% auto 0;
 
	padding: 0;
 
    width: 520px;
 
    margin: 10% auto 0;
 
    padding: 0;
 
}
 

	
 
#login div.color,#register div.color {
 
	clear: both;
 
	overflow: hidden;
 
	background: #FFF;
 
	margin: 10px auto 0;
 
	padding: 3px 3px 3px 0;
 
    clear: both;
 
    overflow: hidden;
 
    background: #FFF;
 
    margin: 10px auto 0;
 
    padding: 3px 3px 3px 0;
 
}
 

	
 
#login div.color a,#register div.color a {
 
	width: 20px;
 
	height: 20px;
 
	display: block;
 
	float: left;
 
	margin: 0 0 0 3px;
 
	padding: 0;
 
    width: 20px;
 
    height: 20px;
 
    display: block;
 
    float: left;
 
    margin: 0 0 0 3px;
 
    padding: 0;
 
}
 

	
 
#login div.title h5,#register div.title h5 {
 
	color: #fff;
 
	margin: 10px;
 
	padding: 0;
 
    color: #fff;
 
    margin: 10px;
 
    padding: 0;
 
}
 

	
 
#login div.form div.fields div.field,#register div.form div.fields div.field
 
	{
 
	clear: both;
 
	overflow: hidden;
 
	margin: 0;
 
	padding: 0 0 10px;
 
    {
 
    clear: both;
 
    overflow: hidden;
 
    margin: 0;
 
    padding: 0 0 10px;
 
}
 

	
 
#login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message
 
	{
 
	height: 1%;
 
	display: block;
 
	color: red;
 
	margin: 8px 0 0;
 
	padding: 0;
 
	max-width: 320px;
 
    {
 
    height: 1%;
 
    display: block;
 
    color: red;
 
    margin: 8px 0 0;
 
    padding: 0;
 
    max-width: 320px;
 
}
 

	
 
#login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label
 
	{
 
	color: #000;
 
	font-weight: 700;
 
    {
 
    color: #000;
 
    font-weight: 700;
 
}
 

	
 
#login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input
 
	{
 
	float: left;
 
	margin: 0;
 
	padding: 0;
 
    {
 
    float: left;
 
    margin: 0;
 
    padding: 0;
 
}
 

	
 
#login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox
 
	{
 
	margin: 0 0 0 184px;
 
	padding: 0;
 
    {
 
    margin: 0 0 0 184px;
 
    padding: 0;
 
}
 

	
 
#login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label
 
	{
 
	color: #565656;
 
	font-weight: 700;
 
    {
 
    color: #565656;
 
    font-weight: 700;
 
}
 

	
 
#login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input
 
	{
 
	color: #000;
 
	font-size: 1em;
 
	font-weight: 700;
 
	margin: 0;
 
    {
 
    color: #000;
 
    font-size: 1em;
 
    font-weight: 700;
 
    margin: 0;
 
}
 

	
 
#changeset_content .container .wrapper,#graph_content .container .wrapper
 
	{
 
	width: 600px;
 
    {
 
    width: 600px;
 
}
 

	
 
#changeset_content .container .left {
 
	float: left;
 
	width: 75%;
 
	padding-left: 5px;
 
    float: left;
 
    width: 75%;
 
    padding-left: 5px;
 
}
 

	
 
#changeset_content .container .left .date,.ac .match {
 
	font-weight: 700;
 
	padding-top: 5px;
 
	padding-bottom: 5px;
 
    font-weight: 700;
 
    padding-top: 5px;
 
    padding-bottom: 5px;
 
}
 

	
 
div#legend_container table td,div#legend_choices table td {
 
	border: none !important;
 
	height: 20px !important;
 
	padding: 0 !important;
 
    border: none !important;
 
    height: 20px !important;
 
    padding: 0 !important;
 
}
 

	
 
.q_filter_box {
 
	-webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
 
	-webkit-border-radius: 4px;
 
	-moz-border-radius: 4px;
 
	border-radius: 4px;
 
    -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;
 
    border: 0 none;
 
    color: #AAAAAA;
 
    margin-bottom: -4px;
 
    margin-top: -4px;
 
    padding-left: 3px;		
 
    padding-left: 3px;
 
}
 

	
 
#node_filter {
 
	border: 0px solid #545454;
 
	color: #AAAAAA;
 
	padding-left: 3px;
 
    border: 0px solid #545454;
 
    color: #AAAAAA;
 
    padding-left: 3px;
 
}
 

	
 

	
 
.group_members_wrap{
 
	min-height: 85px;
 
	padding-left: 20px;
 
    min-height: 85px;
 
    padding-left: 20px;
 
}
 

	
 
.group_members .group_member{
 
	height: 30px;
 
	padding:0px 0px 0px 0px;
 
    height: 30px;
 
    padding:0px 0px 0px 0px;
 
}
 

	
 
.reviewers_member{
 
    height: 15px;
 
    padding:0px 0px 0px 10px;	
 
    padding:0px 0px 0px 10px;
 
}
 

	
 
.emails_wrap{
 
	padding: 0px 20px;
 
    padding: 0px 20px;
 
}
 

	
 
.emails_wrap .email_entry{
 
    height: 30px;
 
    padding:0px 0px 0px 10px;
 
}
 
.emails_wrap .email_entry .email{
 
	float: left
 
    float: left
 
}
 
.emails_wrap .email_entry .email_action{
 
	float: left
 
    float: left
 
}
 

	
 
.ips_wrap{
 
    padding: 0px 20px;
 
}
 

	
 
.ips_wrap .ip_entry{
 
    height: 30px;
 
    padding:0px 0px 0px 10px;
 
}
 
.ips_wrap .ip_entry .ip{
 
    float: left
 
}
 
.ips_wrap .ip_entry .ip_action{
 
    float: left
 
}
 

	
 

	
 
/*README STYLE*/
 

	
 
div.readme {
 
	padding:0px;
 
    padding:0px;
 
}
 

	
 
div.readme h2 {
 
    font-weight: normal;
 
}
 

	
 
div.readme .readme_box {
 
    background-color: #fafafa;
 
}
 

	
 
div.readme .readme_box {
 
clear:both;
 
overflow:hidden;
 
margin:0;
 
padding:0 20px 10px;
 
}
 

	
 
div.readme .readme_box h1, div.readme .readme_box h2, div.readme .readme_box h3, div.readme .readme_box h4, div.readme .readme_box h5, div.readme .readme_box h6 {
 
border-bottom: 0 !important;
 
margin: 0 !important;
 
padding: 0 !important;
 
line-height: 1.5em !important;
 
}
 

	
 

	
 
div.readme .readme_box h1:first-child {
 
padding-top: .25em !important;
 
}
 

	
 
div.readme .readme_box h2, div.readme .readme_box h3 {
 
margin: 1em 0 !important;
 
}
 

	
 
div.readme .readme_box h2 {
 
margin-top: 1.5em !important;
 
border-top: 4px solid #e0e0e0 !important;
 
padding-top: .5em !important;
 
}
 

	
 
div.readme .readme_box p {
 
color: black !important;
 
margin: 1em 0 !important;
 
line-height: 1.5em !important;
 
}
 

	
 
div.readme .readme_box ul {
 
list-style: disc !important;
 
margin: 1em 0 1em 2em !important;
 
}
 

	
 
div.readme .readme_box ol {
 
list-style: decimal;
 
margin: 1em 0 1em 2em !important;
 
}
 

	
 
div.readme .readme_box pre, code {
 
font: 12px "Bitstream Vera Sans Mono","Courier",monospace;
 
}
 

	
 
div.readme .readme_box code {
 
    font-size: 12px !important;
 
    background-color: ghostWhite !important;
 
    color: #444 !important;
 
    padding: 0 .2em !important;
 
    border: 1px solid #dedede !important;
 
}
 

	
 
div.readme .readme_box pre code {
 
	padding: 0 !important;
 
	font-size: 12px !important;
 
	background-color: #eee !important;
 
	border: none !important;
 
    padding: 0 !important;
 
    font-size: 12px !important;
 
    background-color: #eee !important;
 
    border: none !important;
 
}
 

	
 
div.readme .readme_box pre {
 
	margin: 1em 0;
 
	font-size: 12px;
 
	background-color: #eee;
 
	border: 1px solid #ddd;
 
	padding: 5px;
 
	color: #444;
 
	overflow: auto;
 
	-webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
 
	-webkit-border-radius: 3px;
 
	-moz-border-radius: 3px;
 
	border-radius: 3px;
 
    margin: 1em 0;
 
    font-size: 12px;
 
    background-color: #eee;
 
    border: 1px solid #ddd;
 
    padding: 5px;
 
    color: #444;
 
    overflow: auto;
 
    -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
 
    -webkit-border-radius: 3px;
 
    -moz-border-radius: 3px;
 
    border-radius: 3px;
 
}
 

	
 
div.readme .readme_box table {
 
    display: table;
 
	border-collapse: separate;
 
	border-spacing: 2px;
 
	border-color: gray;
 
	width: auto !important;
 
    border-collapse: separate;
 
    border-spacing: 2px;
 
    border-color: gray;
 
    width: auto !important;
 
}
 

	
 

	
 
/** RST STYLE **/
 

	
 

	
 
div.rst-block {
 
    padding:0px;
 
}
 

	
 
div.rst-block h2 {
 
    font-weight: normal;
 
}
 

	
 
div.rst-block  {
 
    background-color: #fafafa;
 
}
 

	
 
div.rst-block  {
 
clear:both;
 
overflow:hidden;
 
margin:0;
 
padding:0 20px 10px;
 
}
 

	
 
div.rst-block  h1, div.rst-block  h2, div.rst-block  h3, div.rst-block  h4, div.rst-block  h5, div.rst-block  h6 {
 
border-bottom: 0 !important;
 
margin: 0 !important;
 
padding: 0 !important;
 
line-height: 1.5em !important;
 
}
 

	
 

	
 
div.rst-block  h1:first-child {
 
padding-top: .25em !important;
 
}
 

	
 
div.rst-block  h2, div.rst-block  h3 {
 
margin: 1em 0 !important;
 
}
 

	
 
div.rst-block  h2 {
 
margin-top: 1.5em !important;
 
border-top: 4px solid #e0e0e0 !important;
 
padding-top: .5em !important;
 
}
 

	
 
div.rst-block  p {
 
color: black !important;
 
margin: 1em 0 !important;
 
line-height: 1.5em !important;
 
}
 

	
 
div.rst-block  ul {
 
list-style: disc !important;
 
margin: 1em 0 1em 2em !important;
 
}
 

	
 
div.rst-block  ol {
 
list-style: decimal;
 
margin: 1em 0 1em 2em !important;
 
}
 

	
 
div.rst-block  pre, code {
 
font: 12px "Bitstream Vera Sans Mono","Courier",monospace;
 
}
 

	
 
div.rst-block  code {
 
    font-size: 12px !important;
 
    background-color: ghostWhite !important;
 
    color: #444 !important;
 
    padding: 0 .2em !important;
 
    border: 1px solid #dedede !important;
 
}
 

	
 
div.rst-block  pre code {
 
    padding: 0 !important;
 
    font-size: 12px !important;
 
    background-color: #eee !important;
 
    border: none !important;
 
}
 

	
 
div.rst-block  pre {
 
    margin: 1em 0;
 
    font-size: 12px;
 
    background-color: #eee;
 
    border: 1px solid #ddd;
 
    padding: 5px;
 
    color: #444;
 
    overflow: auto;
 
    -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
 
    -webkit-border-radius: 3px;
 
    -moz-border-radius: 3px;
 
    border-radius: 3px;
 
}
 

	
 

	
 
/** comment main **/
 
.comments {
 
    padding:10px 20px;
 
}
 

	
 
.comments .comment {
 
    border: 1px solid #ddd;
 
    margin-top: 10px;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;    
 
    border-radius: 4px;
 
}
 

	
 
.comments .comment .meta {
 
    background: #f8f8f8;
 
    padding: 4px;
 
    border-bottom: 1px solid #ddd;
 
    height: 18px;
 
}
 

	
 
.comments .comment .meta img {
 
    vertical-align: middle;
 
}
 

	
 
.comments .comment .meta .user {
 
    font-weight: bold;
 
    float: left;
 
    padding: 4px 2px 2px 2px;
 
}
 

	
 
.comments .comment .meta .date {
 
	float: left;
 
	padding:4px 4px 0px 4px;
 
    float: left;
 
    padding:4px 4px 0px 4px;
 
}
 

	
 
.comments .comment .text {
 
    background-color: #FAFAFA;
 
}
 
.comment .text div.rst-block p {
 
	margin: 0.5em 0px !important;
 
    margin: 0.5em 0px !important;
 
}
 

	
 
.comments .comments-number{
 
	padding:0px 0px 10px 0px;
 
	font-weight: bold;
 
	color: #666;
 
	font-size: 16px;
 
    padding:0px 0px 10px 0px;
 
    font-weight: bold;
 
    color: #666;
 
    font-size: 16px;
 
}
 

	
 
/** comment form **/
 

	
 
.status-block{
 
    height:80px;
 
    clear:both	
 
    clear:both
 
}
 

	
 
.comment-form .clearfix{
 
	background: #EEE;
 
    background: #EEE;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;
 
    padding: 10px;
 
}
 

	
 
div.comment-form {
 
    margin-top: 20px;
 
}
 

	
 
.comment-form strong {
 
    display: block;
 
    margin-bottom: 15px;
 
}
 

	
 
.comment-form textarea {
 
    width: 100%;
 
    height: 100px;
 
    font-family: 'Monaco', 'Courier', 'Courier New', monospace;
 
}
 

	
 
form.comment-form {
 
    margin-top: 10px;
 
    margin-left: 10px;
 
}
 

	
 
.comment-form-submit {
 
    margin-top: 5px;
 
    margin-left: 525px;
 
}
 

	
 
.file-comments {
 
    display: none;
 
}
 

	
 
.comment-form .comment {
 
    margin-left: 10px;
 
}
 

	
 
.comment-form .comment-help{
 
    padding: 0px 0px 5px 0px;
 
    color: #666;
 
}
 

	
 
.comment-form .comment-button{
 
	padding-top:5px;
 
    padding-top:5px;
 
}
 

	
 
.add-another-button {
 
    margin-left: 10px;
 
    margin-top: 10px;
 
    margin-bottom: 10px;
 
}
 

	
 
.comment .buttons {
 
	float: right;
 
	padding:2px 2px 0px 0px;
 
    float: right;
 
    padding:2px 2px 0px 0px;
 
}
 

	
 

	
 
.show-inline-comments{
 
	position: relative;
 
	top:1px
 
    position: relative;
 
    top:1px
 
}
 

	
 
/** comment inline form **/
 
.comment-inline-form .overlay{
 
	display: none;
 
    display: none;
 
}
 
.comment-inline-form .overlay.submitting{
 
	display:block;
 
    display:block;
 
    background: none repeat scroll 0 0 white;
 
    font-size: 16px;
 
    opacity: 0.5;
 
    position: absolute;
 
    text-align: center;
 
    vertical-align: top;
 

	
 
}
 
.comment-inline-form .overlay.submitting .overlay-text{
 
	width:100%;
 
	margin-top:5%;
 
    width:100%;
 
    margin-top:5%;
 
}
 

	
 
.comment-inline-form .clearfix{
 
    background: #EEE;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;
 
    padding: 5px;
 
}
 

	
 
div.comment-inline-form {
 
    padding:4px 0px 6px 0px;
 
}
 

	
 

	
 
tr.hl-comment{
 
/*
 
	background-color: #FFFFCC !important;
 
    background-color: #FFFFCC !important;
 
*/
 
}
 

	
 
/*
 
tr.hl-comment pre {
 
	border-top: 2px solid #FFEE33;
 
	border-left: 2px solid #FFEE33;
 
	border-right: 2px solid #FFEE33;
 
    border-top: 2px solid #FFEE33;
 
    border-left: 2px solid #FFEE33;
 
    border-right: 2px solid #FFEE33;
 
}
 
*/
 

	
 
.comment-inline-form strong {
 
    display: block;
 
    margin-bottom: 15px;
 
}
 

	
 
.comment-inline-form textarea {
 
    width: 100%;
 
    height: 100px;
 
    font-family: 'Monaco', 'Courier', 'Courier New', monospace;
 
}
 

	
 
form.comment-inline-form {
 
    margin-top: 10px;
 
    margin-left: 10px;
 
}
 

	
 
.comment-inline-form-submit {
 
    margin-top: 5px;
 
    margin-left: 525px;
 
}
 

	
 
.file-comments {
 
    display: none;
 
}
 

	
 
.comment-inline-form .comment {
 
    margin-left: 10px;
 
}
 

	
 
.comment-inline-form .comment-help{
 
    padding: 0px 0px 2px 0px;
 
    color: #666666;
 
    font-size: 10px;
 
}
 

	
 
.comment-inline-form .comment-button{
 
    padding-top:5px;
 
}
 

	
 
/** comment inline **/
 
.inline-comments {
 
    padding:10px 20px;
 
}
 

	
 
.inline-comments div.rst-block  {
 
	clear:both;
 
	overflow:hidden;
 
	margin:0;
 
	padding:0 20px 0px;
 
    clear:both;
 
    overflow:hidden;
 
    margin:0;
 
    padding:0 20px 0px;
 
}
 
.inline-comments .comment {
 
    border: 1px solid #ddd;
 
    -webkit-border-radius: 4px;
 
    -moz-border-radius: 4px;
 
    border-radius: 4px;
 
    margin: 3px 3px 5px 5px;
 
    background-color: #FAFAFA;
 
}
 
.inline-comments .add-comment {
 
	padding: 2px 4px 8px 5px;
 
    padding: 2px 4px 8px 5px;
 
}
 

	
 
.inline-comments .comment-wrapp{
 
	padding:1px;
 
    padding:1px;
 
}
 
.inline-comments .comment .meta {
 
    background: #f8f8f8;
 
    padding: 4px;
 
    border-bottom: 1px solid #ddd;
 
    height: 20px;
 
}
 

	
 
.inline-comments .comment .meta img {
 
    vertical-align: middle;
 
}
 

	
 
.inline-comments .comment .meta .user {
 
    font-weight: bold;
 
    float:left;
 
    padding: 3px;
 
}
 

	
 
.inline-comments .comment .meta .date {
 
    float:left;
 
    padding: 3px;
 
}
 

	
 
.inline-comments .comment .text {
 
    background-color: #FAFAFA;
 
}
 

	
 
.inline-comments .comments-number{
 
    padding:0px 0px 10px 0px;
 
    font-weight: bold;
 
    color: #666;
 
    font-size: 16px;
 
}
 
.inline-comments-button .add-comment{
 
	margin:2px 0px 8px 5px !important
 
    margin:2px 0px 8px 5px !important
 
}
 

	
 

	
 
.notification-paginator{
 
    padding: 0px 0px 4px 16px;
 
    float: left;    	
 
    float: left;
 
}
 

	
 
.menu_link_user{
 
    padding: 10px 8px 8px 8px !important;
 
}
 

	
 
.menu_link_notifications {
 
	padding: 4px 4px !important;
 
	margin: 7px 4px 0px 0px !important;
 
	text-align: center;
 
	color:#888 !important;
 
	font-size: 10px;
 
	background-color: #DEDEDE !important;
 
	border-radius: 4px !important;
 
	-webkit-border-radius: 4px !important;
 
	-moz-border-radius: 4px !important;  	
 
    padding: 4px 4px !important;
 
    margin: 7px 4px 0px 0px !important;
 
    text-align: center;
 
    color:#888 !important;
 
    font-size: 10px;
 
    background-color: #DEDEDE !important;
 
    border-radius: 4px !important;
 
    -webkit-border-radius: 4px !important;
 
    -moz-border-radius: 4px !important;
 
}
 

	
 
.notification-header{
 
	padding-top:6px;
 
    padding-top:6px;
 
}
 
.notification-header .desc{
 
	font-size: 16px;
 
    font-size: 16px;
 
    height: 24px;
 
    float: left
 
}
 
.notification-list .container.unread{
 
	background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6);
 
    background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6);
 
}
 
.notification-header .gravatar{
 
    background: none repeat scroll 0 0 transparent;
 
    padding: 0px 0px 0px 8px;	
 
    padding: 0px 0px 0px 8px;
 
}
 
.notification-list .container .notification-header .desc{
 
    font-weight: bold;
 
    font-size: 17px;
 
}
 
.notification-table{
 
	border: 1px solid #ccc;
 
    border: 1px solid #ccc;
 
    -webkit-border-radius: 6px 6px 6px 6px;
 
    -moz-border-radius: 6px 6px 6px 6px;
 
    border-radius: 6px 6px 6px 6px;
 
    clear: both;
 
    margin: 0px 20px 0px 20px;
 
}
 
.notification-header .delete-notifications{
 
    float: right;
 
    padding-top: 8px;
 
    cursor: pointer;
 
}
 
.notification-header .read-notifications{
 
    float: right;
 
    padding-top: 8px;
 
    cursor: pointer;
 
}
 
.notification-subject{
 
    clear:both;
 
    border-bottom: 1px solid #eee;
 
    padding:5px 0px 5px 38px;
 
}
 

	
 
.notification-body{
 
	clear:both;
 
	margin: 34px 2px 2px 8px
 
    clear:both;
 
    margin: 34px 2px 2px 8px
 
}
 

	
 
/****
 
PULL REQUESTS
 
*****/
 
.pullrequests_section_head {
 
   padding:10px 10px 10px 0px;
 
   font-size:16px;
 
   font-weight: bold;
 
}
 

	
 
/****
 
  PERMS
 
*****/
 
#perms .perms_section_head {
 
   padding:10px 10px 10px 0px;
 
   font-size:16px;
 
   font-weight: bold;
 
}
 

	
 
#perms .perm_tag{
 
  padding: 1px 3px 1px 3px;
 
  font-size: 10px;
 
  font-weight: bold;
 
  text-transform: uppercase;
 
  white-space: nowrap;
 
  -webkit-border-radius: 3px;
 
  -moz-border-radius: 3px;
 
  border-radius: 3px;
 
}
 

	
 
#perms .perm_tag.admin{
 
  background-color: #B94A48;
 
  color: #ffffff;
 
}
 

	
 
#perms .perm_tag.write{
 
  background-color: #DB7525;
 
  color: #ffffff;    
 
  color: #ffffff;
 
}
 

	
 
#perms .perm_tag.read{
 
  background-color: #468847;
 
  color: #ffffff;    
 
  color: #ffffff;
 
}
 

	
 
#perms .perm_tag.none{
 
  background-color: #bfbfbf;
 
  color: #ffffff;    
 
  color: #ffffff;
 
}
 

	
 
.perm-gravatar{
 
	vertical-align:middle;
 
	padding:2px;
 
    vertical-align:middle;
 
    padding:2px;
 
}
 
.perm-gravatar-ac{
 
    vertical-align:middle;
 
    padding:2px;
 
    width: 14px;
 
    height: 14px;	
 
    height: 14px;
 
}
 

	
 
/*****************************************************************************
 
                                  DIFFS CSS
 
******************************************************************************/
 

	
 
div.diffblock {
 
    overflow: auto;
 
    padding: 0px;
 
    border: 1px solid #ccc;
 
    background: #f8f8f8;
 
    font-size: 100%;
 
    line-height: 100%;
 
    /* new */
 
    line-height: 125%;
 
    -webkit-border-radius: 6px 6px 0px 0px;
 
    -moz-border-radius: 6px 6px 0px 0px;
 
    border-radius: 6px 6px 0px 0px;     
 
    border-radius: 6px 6px 0px 0px;
 
}
 
div.diffblock.margined{
 
    margin: 0px 20px 0px 20px;
 
}
 
div.diffblock .code-header{
 
    border-bottom: 1px solid #CCCCCC;
 
    background: #EEEEEE;
 
    padding:10px 0 10px 0;
 
    height: 14px;
 
}
 

	
 
div.diffblock .code-header.banner{
 
    border-bottom: 1px solid #CCCCCC;
 
    background: #EEEEEE;
 
    height: 14px;
 
    margin: 0px 95px 0px 95px;
 
    padding: 3px 3px 11px 3px;
 
}
 

	
 
div.diffblock .code-header.cv{
 
    height: 34px;
 
}
 
div.diffblock .code-header-title{
 
	padding: 0px 0px 10px 5px !important;
 
	margin: 0 !important;
 
    padding: 0px 0px 10px 5px !important;
 
    margin: 0 !important;
 
}
 
div.diffblock .code-header .hash{
 
    float: left;
 
    padding: 2px 0 0 2px;
 
}
 
div.diffblock .code-header .date{
 
    float:left;
 
    text-transform: uppercase;
 
    padding: 2px 0px 0px 2px;
 
}
 
div.diffblock .code-header div{
 
    margin-left:4px;
 
    font-weight: bold;
 
    font-size: 14px;
 
}
 

	
 
div.diffblock .parents {
 
    float: left;
 
    height: 26px;
 
    width:100px;
 
    font-size: 10px;
 
    font-weight: 400;
 
    vertical-align: middle;
 
    padding: 0px 2px 2px 2px;
 
    background-color:#eeeeee;
 
    border-bottom: 1px solid #CCCCCC;
 
}
 

	
 
div.diffblock .children {
 
    float: right;
 
    height: 26px;
 
    width:100px;
 
    font-size: 10px;
 
    font-weight: 400;
 
    vertical-align: middle;
 
    text-align: right;
 
    padding: 0px 2px 2px 2px;
 
    background-color:#eeeeee;
 
    border-bottom: 1px solid #CCCCCC;
 
}
 

	
 
div.diffblock .code-body{
 
    background: #FFFFFF;
 
}
 
div.diffblock pre.raw{
 
    background: #FFFFFF;
 
    color:#000000;
 
}
 
table.code-difftable{
 
    border-collapse: collapse;
 
    width: 99%;
 
}
 
table.code-difftable td {
 
    padding: 0 !important; 
 
    background: none !important; 
 
    padding: 0 !important;
 
    background: none !important;
 
    border:0 !important;
 
    vertical-align: none !important;
 
}
 
table.code-difftable .context{
 
    background:none repeat scroll 0 0 #DDE7EF;
 
}
 
table.code-difftable .add{
 
    background:none repeat scroll 0 0 #DDFFDD;
 
}
 
table.code-difftable .add ins{
 
    background:none repeat scroll 0 0 #AAFFAA;
 
    text-decoration:none;
 
}
 
table.code-difftable .del{
 
    background:none repeat scroll 0 0 #FFDDDD;
 
}
 
table.code-difftable .del del{
 
    background:none repeat scroll 0 0 #FFAAAA;
 
    text-decoration:none;
 
}
 

	
 
/** LINE NUMBERS **/
 
table.code-difftable .lineno{
 

	
 
    padding-left:2px;
 
    padding-right:2px;
 
    text-align:right;
 
    width:32px;
 
    -moz-user-select:none;
 
    -webkit-user-select: none;
 
    border-right: 1px solid #CCC !important;
 
    border-left: 0px solid #CCC !important;
 
    border-top: 0px solid #CCC !important;
 
    border-bottom: none !important;
 
    vertical-align: middle !important;
 
    
 

	
 
}
 
table.code-difftable .lineno.new {
 
}
 
table.code-difftable .lineno.old {
 
}
 
table.code-difftable .lineno a{
 
    color:#747474 !important;
 
    font:11px "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace !important;
 
    letter-spacing:-1px;
 
    text-align:right;
 
    padding-right: 2px;
 
    cursor: pointer;
 
    display: block;
 
    width: 32px;
 
}
 

	
 
table.code-difftable .lineno-inline{
 
    background:none repeat scroll 0 0 #FFF !important;
 
    padding-left:2px;
 
    padding-right:2px;
 
    text-align:right;
 
    width:30px;
 
    -moz-user-select:none;
 
    -webkit-user-select: none;
 
}
 

	
 
/** CODE **/
 
table.code-difftable .code { 
 
table.code-difftable .code {
 
    display: block;
 
    width: 100%;
 
}
 
table.code-difftable .code td{
 
    margin:0;
 
    padding:0;
 
}
 
table.code-difftable .code pre{
 
    margin:0;
 
    padding:0;
 
    height: 17px;
 
    line-height: 17px;
 
}
 

	
 

	
 
.diffblock.margined.comm .line .code:hover{
 
    background-color:#FFFFCC !important;
 
    cursor: pointer !important;
 
    background-image:url("../images/icons/comment_add.png") !important;
 
    background-repeat:no-repeat !important;
 
    background-position: right !important;
 
    background-position: 0% 50% !important;
 
}
 
.diffblock.margined.comm .line .code.no-comment:hover{
 
	background-image: none !important;
 
	cursor: auto !important;
 
	background-color: inherit !important;
 
	
 
    background-image: none !important;
 
    cursor: auto !important;
 
    background-color: inherit !important;
 
}
 

	
 
div:target {
 
	border: solid 2px #ee0 !important;
 
	margin: -2px;
 
}
 
    border: solid 2px #ee0 !important;
 
    margin: -2px;
 
}
rhodecode/templates/base/base.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="root.html"/>
 

	
 
<!-- HEADER -->
 
<div id="header">
 
    <div id="header-inner" class="title hover">
 
        <div id="logo">
 
            <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
 
        </div>
 
        <!-- MENU -->
 
        ${self.page_nav()}
 
        <!-- END MENU -->
 
        ${self.body()}
 
    </div>
 
</div>
 
<!-- END HEADER -->
 

	
 
<!-- CONTENT -->
 
<div id="content">
 
    <div class="flash_msg">
 
        <% messages = h.flash.pop_messages() %>
 
        % if messages:
 
        <ul id="flash-messages">
 
            % for message in messages:
 
            <li class="${message.category}_msg">${message}</li>
 
            % endfor
 
        </ul>
 
        % endif
 
    </div>
 
    <div id="main">
 
        ${next.main()}
 
    </div>
 
</div>
 
<!-- END CONTENT -->
 

	
 
<!-- FOOTER -->
 
<div id="footer">
 
   <div id="footer-inner" class="title">
 
       <div>
 
           <p class="footer-link">
 
                <a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
 
           </p>
 
           <p class="footer-link-right">
 
               <a href="${h.url('rhodecode_official')}">RhodeCode${'-%s' % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}</a>
 
               ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski
 
           </p>
 
       </div>
 
   </div>
 
</div>
 
<!-- END FOOTER -->
 

	
 
### MAKO DEFS ###
 
<%def name="page_nav()">
 
    ${self.menu()}
 
</%def>
 

	
 
<%def name="breadcrumbs()">
 
    <div class="breadcrumbs">
 
    ${self.breadcrumbs_links()}
 
    </div>
 
</%def>
 

	
 
<%def name="usermenu()">
 
    ## USER MENU
 
    <li>
 
      <a class="menu_link" id="quick_login_link">
 
          <span class="icon" style="padding:5px 5px 0px 5px">
 
             <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
 
          </span>
 
          %if c.rhodecode_user.username != 'default':
 
            <span class="menu_link_user">${c.rhodecode_user.username}</span>
 
            %if c.unread_notifications != 0:
 
              <span class="menu_link_notifications">${c.unread_notifications}</span>
 
            %endif
 
          %else:
 
              <span>${_('Not logged in')}</span>
 
          %endif
 
      </a>
 

	
 
  <div class="user-menu">
 
      <div id="quick_login">
 
        %if c.rhodecode_user.username == 'default':
 
            <h4>${_('Login to your account')}</h4>
 
            ${h.form(h.url('login_home',came_from=h.url.current()))}
 
            <div class="form">
 
                <div class="fields">
 
                    <div class="field">
 
                        <div class="label">
 
                            <label for="username">${_('Username')}:</label>
 
                        </div>
 
                        <div class="input">
 
                            ${h.text('username',class_='focus',size=40)}
 
                        </div>
 

	
 
                    </div>
 
                    <div class="field">
 
                        <div class="label">
 
                            <label for="password">${_('Password')}:</label>
 
                        </div>
 
                        <div class="input">
 
                            ${h.password('password',class_='focus',size=40)}
 
                        </div>
 

	
 
                    </div>
 
                    <div class="buttons">
 
                        <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
 
                        <div class="register">
 
                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
 
                         ${h.link_to(_("Don't have an account ?"),h.url('register'))}
 
                        %endif
 
                        </div>
 
                        <div class="submit">
 
                            ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
 
                        </div>
 
                    </div>
 
                </div>
 
            </div>
 
            ${h.end_form()}
 
        %else:
 
            <div class="links_left">
 
                <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
 
                <div class="email">${c.rhodecode_user.email}</div>
 
                <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
 
                <div class="inbox"><a href="${h.url('notifications')}">${_('Inbox')}: ${c.unread_notifications}</a></div>
 
            </div>
 
            <div class="links_right">
 
            <ol class="links">
 
              <li>${h.link_to(_(u'Home'),h.url('home'))}</li>
 
              <li>${h.link_to(_(u'Journal'),h.url('journal'))}</li>
 
              <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
 
              <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
 
            </ol>
 
            </div>
 
        %endif
 
      </div>
 
  </div>
 

	
 
    </li>
 
</%def>
 

	
 
<%def name="menu(current=None)">
 
        <%
 
        def is_current(selected):
 
            if selected == current:
 
                return h.literal('class="current"')
 
        %>
 
        <ul id="quick">
 
          <!-- repo switcher -->
 
          <li>
 
              <a class="menu_link" id="repo_switcher" title="${_('Switch repository')}" href="#">
 
              <span class="icon">
 
                  <img src="${h.url('/images/icons/database.png')}" alt="${_('Products')}" />
 
              </span>
 
              <span>${_('Repositories')}</span>
 
              </a>
 
              <ul id="repo_switcher_list" class="repo_switcher">
 
                  <li>
 
                      <a href="#">${_('loading...')}</a>
 
                  </li>
 
              </ul>
 
          </li>
 
        ## we render this menu only not for those pages
 
        %if current not in ['home','admin', 'search', 'journal']:
 
            ##REGULAR MENU
 
            <li ${is_current('summary')}>
 
               <a class="menu_link" title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
 
               <span class="icon">
 
                   <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
 
               </span>
 
               <span>${_('Summary')}</span>
 
               </a>
 
            </li>
 
            <li ${is_current('changelog')}>
 
               <a class="menu_link" title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
 
               <span class="icon">
 
                   <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
 
               </span>
 
               <span>${_('Changelog')}</span>
 
               </a>
 
            </li>
 
            <li ${is_current('switch_to')}>
 
               <a class="menu_link" id="branch_tag_switcher" title="${_('Switch to')}" href="#">
 
               <span class="icon">
 
                   <img src="${h.url('/images/icons/arrow_switch.png')}" alt="${_('Switch to')}" />
 
               </span>
 
               <span>${_('Switch to')}</span>
 
               </a>
 
                <ul id="switch_to_list" class="switch_to">
 
                    <li><a href="#">${_('loading...')}</a></li>
 
                </ul>
 
            </li>
 
            <li ${is_current('files')}>
 
               <a class="menu_link" title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
 
               <span class="icon">
 
                   <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
 
               </span>
 
               <span>${_('Files')}</span>
 
               </a>
 
            </li>
 
            <li ${is_current('options')}>
 
               <a class="menu_link" title="${_('Options')}" href="#">
 
               <span class="icon">
 
                   <img src="${h.url('/images/icons/table_gear.png')}" alt="${_('Admin')}" />
 
               </span>
 
               <span>${_('Options')}</span>
 
               </a>
 
               <ul>
 
               %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
                 %if h.HasPermissionAll('hg.admin')('access settings on repository'):
 
                     <li>${h.link_to(_('repository settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
 
                 %else:
 
                     <li>${h.link_to(_('repository settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
 
                 %endif
 
               %endif
 

	
 
                <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
 
                %if h.is_hg(c.rhodecode_repo):
 
                 <li>${h.link_to(_('open new pull request'),h.url('pullrequest_home',repo_name=c.repo_name),class_='pull_request')}</li>
 
                %endif
 
                %if c.rhodecode_db_repo.fork:
 
                 <li>${h.link_to(_('compare fork'),h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref=request.GET.get('branch') or 'default',other_ref_type='branch',other_ref='default',repo=c.rhodecode_db_repo.fork.repo_name),class_='compare_request')}</li>
 
                %endif
 
                <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
 

	
 
                %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
 
                  %if c.rhodecode_db_repo.locked[0]:
 
                    <li>${h.link_to(_('unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
 
                  %else:
 
                    <li>${h.link_to(_('lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
 
                  %endif
 
                %endif
 

	
 
                % if h.HasPermissionAll('hg.admin')('access admin main page'):
 
                 <li>
 
                   ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
 
                    <%def name="admin_menu()">
 
                    <ul>
 
                        <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
 
                        <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
 
                        <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
 
                        <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
 
                        <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
 
                        <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
 
                        <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
 
                        <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
 
                        <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
 
                    </ul>
 
                    </%def>
 
                    ## ADMIN MENU
 
                    ${admin_menu()}
 
                 </li>
 
                % endif
 
               </ul>
 
            </li>
 
            <li>
 
                <a class="menu_link" title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
 
                <span class="icon_short">
 
                    <img src="${h.url('/images/icons/heart.png')}" alt="${_('Followers')}" />
 
                </span>
 
                <span id="current_followers_count" class="short">${c.repository_followers}</span>
 
                </a>
 
            </li>
 
            <li>
 
                <a class="menu_link" title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
 
                <span class="icon_short">
 
                    <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Forks')}" />
 
                </span>
 
                <span class="short">${c.repository_forks}</span>
 
                </a>
 
            </li>
 
            <li>
 
                <a class="menu_link" title="${_('Pull requests')}" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}">
 
                <span class="icon_short">
 
                    <img src="${h.url('/images/icons/arrow_join.png')}" alt="${_('Pull requests')}" />
 
                </span>
 
                <span class="short">${c.repository_pull_requests}</span>
 
                </a>
 
            </li>
 
            ${usermenu()}
 
            <script type="text/javascript">
 
                YUE.on('branch_tag_switcher','mouseover',function(){
 
                   var loaded = YUD.hasClass('branch_tag_switcher','loaded');
 
                   if(!loaded){
 
                       YUD.addClass('branch_tag_switcher','loaded');
 
                       ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list',
 
                           function(o){},
 
                           function(o){YUD.removeClass('branch_tag_switcher','loaded');}
 
                           ,null);
 
                   }
 
                   return false;
 
                });
 
            </script>
 
        %else:
 
            ##ROOT MENU
 
            %if c.rhodecode_user.username != 'default':
 
             <li ${is_current('journal')}>
 
                <a class="menu_link" title="${_('Journal')}"  href="${h.url('journal')}">
 
                <span class="icon">
 
                    <img src="${h.url('/images/icons/book.png')}" alt="${_('Journal')}" />
 
                </span>
 
                <span>${_('Journal')}</span>
 
                </a>
 
             </li>
 
            %else:
 
             <li ${is_current('journal')}>
 
                <a class="menu_link" title="${_('Public journal')}"  href="${h.url('public_journal')}">
 
                <span class="icon">
 
                    <img src="${h.url('/images/icons/book.png')}" alt="${_('Public journal')}" />
 
                </span>
 
                <span>${_('Public journal')}</span>
 
                </a>
 
             </li>
 
            %endif
 
            <li ${is_current('search')}>
 
                <a class="menu_link" title="${_('Search')}"  href="${h.url('search')}">
 
                <span class="icon">
 
                    <img src="${h.url('/images/icons/search_16.png')}" alt="${_('Search')}" />
 
                </span>
 
                <span>${_('Search')}</span>
 
                </a>
 
            </li>
 
            %if h.HasPermissionAll('hg.admin')('access admin main page'):
 
            <li ${is_current('admin')}>
 
               <a class="menu_link" title="${_('Admin')}" href="${h.url('admin_home')}">
 
               <span class="icon">
 
                   <img src="${h.url('/images/icons/cog_edit.png')}" alt="${_('Admin')}" />
 
               </span>
 
               <span>${_('Admin')}</span>
 
               </a>
 
                ${admin_menu()}
 
            </li>
 
            %endif
 
            ${usermenu()}
 
        %endif
 
<script type="text/javascript">
 
    YUE.on('repo_switcher','mouseover',function(){
 
      var target = 'q_filter_rs';
 
      var qfilter_activate = function(){
 
          var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
 
          var func = function(node){
 
              return node.parentNode;
 
          }
 
          q_filter(target,nodes,func);
 
      }
 

	
 
      var loaded = YUD.hasClass('repo_switcher','loaded');
 
      if(!loaded){
 
         YUD.addClass('repo_switcher','loaded');
 
         ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
 
             function(o){qfilter_activate();YUD.get(target).focus()},
 
             function(o){YUD.removeClass('repo_switcher','loaded');}
 
             ,null);
 
      }else{
 
    	 YUD.get(target).focus();
 
         YUD.get(target).focus();
 
      }
 
      return false;
 
     });
 
</script>
 
</%def>
rhodecode/templates/data_table/_dt_elements.html
Show inline comments
 
## DATA TABLE RE USABLE ELEMENTS
 
## usage:
 
## <%namespace name="dt" file="/data_table/_dt_elements.html"/>
 

	
 
<%def name="quick_menu(repo_name)">
 
  <ul class="menu_items hidden">
 
    <li style="border-top:1px solid #003367;margin-left:18px;padding-left:-99px"></li>
 
    <li>
 
       <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=repo_name)}">
 
       <span class="icon">
 
           <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
 
       </span>
 
       <span>${_('Summary')}</span>
 
       </a>
 
    </li>
 
    <li>
 
       <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=repo_name)}">
 
       <span class="icon">
 
           <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
 
       </span>
 
       <span>${_('Changelog')}</span>
 
       </a>
 
    </li>
 
    <li>
 
       <a title="${_('Files')}" href="${h.url('files_home',repo_name=repo_name)}">
 
       <span class="icon">
 
           <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
 
       </span>
 
       <span>${_('Files')}</span>
 
       </a>
 
    </li>
 
    <li>
 
       <a title="${_('Fork')}" href="${h.url('repo_fork_home',repo_name=repo_name)}">
 
       <span class="icon">
 
           <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Fork')}" />
 
       </span>
 
       <span>${_('Fork')}</span>
 
       </a>
 
    </li>
 
  </ul>
 
</%def>
 

	
 
<%def name="repo_name(name,rtype,private,fork_of,short_name=False,admin=False)">
 
    <%
 
    def get_name(name,short_name=short_name):
 
      if short_name:
 
        return name.split('/')[-1]
 
      else:
 
        return name
 
    %>
 
  <div style="white-space: nowrap">
 
   ##TYPE OF REPO
 
   %if h.is_hg(rtype):
 
     <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
 
   %elif h.is_git(rtype):
 
     <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
 
   %endif
 

	
 
   ##PRIVATE/PUBLIC
 
   %if private and c.visual.show_private_icon:
 
     <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
 
   %elif not private and c.visual.show_public_icon:
 
     <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
 
   %endif
 

	
 
   ##NAME
 
   %if admin:
 
    ${h.link_to(get_name(name),h.url('edit_repo',repo_name=name),class_="repo_name")}
 
   %else:
 
    ${h.link_to(get_name(name),h.url('summary_home',repo_name=name),class_="repo_name")}
 
   %endif
 
   %if fork_of:
 
        <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}">
 
        <img class="icon" alt="${_('fork')}" title="${_('Fork of')} ${fork_of.repo_name}" src="${h.url('/images/icons/arrow_divide.png')}"/></a>
 
   %endif
 
  </div>
 
</%def>
 

	
 
<%def name="last_change(last_change)">
 
  <span class="tooltip" date="${last_change}" title="${h.tooltip(h.fmt_date(last_change))}">${h.age(last_change)}</span>
 
</%def>
 

	
 
<%def name="revision(name,rev,tip,author,last_msg)">
 
  <div>
 
  %if rev >= 0:
 
      <pre><a title="${h.tooltip('%s:\n\n%s' % (author,last_msg))}" class="tooltip" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></pre>
 
  %else:
 
      ${_('No changesets yet')}
 
  %endif
 
  </div>
 
</%def>
 

	
 
<%def name="rss(name)">
 
  %if c.rhodecode_user.username != 'default':
 
    <a title="${_('Subscribe to %s rss feed')% name}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=name,api_key=c.rhodecode_user.api_key)}"></a>
 
  %else:
 
    <a title="${_('Subscribe to %s rss feed')% name}" class="rss_icon"  href="${h.url('rss_feed_home',repo_name=name)}"></a>
 
  %endif
 
</%def>
 

	
 
<%def name="atom(name)">
 
  %if c.rhodecode_user.username != 'default':
 
    <a title="${_('Subscribe to %s atom feed')% name}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=name,api_key=c.rhodecode_user.api_key)}"></a>
 
  %else:
 
    <a title="${_('Subscribe to %s atom feed')% name}"  class="atom_icon" href="${h.url('atom_feed_home',repo_name=name)}"></a>
 
  %endif
 
</%def>
 

	
 
<%def name="user_gravatar(email, size=24)">
 
    <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(email, size)}"/> </div>
 
</%def>
 

	
 
<%def name="repo_actions(repo_name, super_user=True)">
 
  <div>
 
    <div style="float:left">
 
    %if super_user:
 
      <a href="${h.url('edit_repo',repo_name=repo_name)}" title="${_('edit')}">
 
        ${h.submit('edit_%s' % repo_name,_('edit'),class_="edit_icon action_button")}
 
      </a>
 
    %else:
 
      <a href="${h.url('repo_settings_home',repo_name=repo_name)}" title="${_('edit')}">
 
        ${h.submit('edit_%s' % repo_name,_('edit'),class_="edit_icon action_button")}
 
      </a>
 
    %endif
 
    </div>
 
    <div style="float:left">
 
    %if super_user:
 
      ${h.form(h.url('repo', repo_name=repo_name),method='delete')}
 
        ${h.submit('remove_%s' % repo_name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
 
      ${h.end_form()}
 
    %else:
 
      ${h.form(h.url('repo_settings_delete', repo_name=repo_name),method='delete')}
 
        ${h.submit('remove_%s' % repo_name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
 
      ${h.end_form()}        
 
      ${h.end_form()}
 
    %endif
 
    </div>
 
  </div>
 
</%def>
 

	
 
<%def name="user_actions(user_id, username)">
 
  ${h.form(h.url('delete_user', id=user_id),method='delete')}
 
      ${h.submit('remove_',_('delete'),id="remove_user_%s" % user_id,
 
      class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
 
  ${h.end_form()}
 
</%def>
 

	
 
<%def name="user_name(user_id, username)">
 
    ${h.link_to(username,h.url('edit_user', id=user_id))}
 
</%def>
 

	
 
<%def name="toggle_follow(repo_id)">
 
  <span id="follow_toggle_${repo_id}" class="following" title="${_('Stop following this repository')}"
 
        onclick="javascript:toggleFollowingRepo(this, ${repo_id},'${str(h.get_token())}')">
 
  </span>
 
</%def>
rhodecode/templates/summary/summary.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('%s Summary') % c.repo_name} - ${c.rhodecode_name}
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${h.link_to(_(u'Home'),h.url('/'))}
 
    &raquo;
 
    ${h.repo_link(c.dbrepo.groups_and_repo)}
 
    &raquo;
 
    ${_('summary')}
 
</%def>
 

	
 
<%def name="page_nav()">
 
    ${self.menu('summary')}
 
</%def>
 

	
 
<%def name="head_extra()">
 
<link href="${h.url('atom_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('repo %s ATOM feed') % c.repo_name}" type="application/atom+xml" />
 
<link href="${h.url('rss_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key)}" rel="alternate" title="${_('repo %s RSS feed') % c.repo_name}" type="application/rss+xml" />
 
</%def>
 

	
 
<%def name="main()">
 
    <%
 
    summary = lambda n:{False:'summary-short'}.get(n)
 
    %>
 
    %if c.show_stats:
 
        <div class="box box-left">
 
    %else:
 
        <div class="box">
 
    %endif
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <!-- end box / title -->
 
    <div class="form">
 
      <div id="summary" class="fields">
 

	
 
             <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Name')}:</label>
 
              </div>
 
              <div class="input ${summary(c.show_stats)}">
 
                  <div style="float:right;padding:5px 0px 0px 5px">
 
                     %if c.rhodecode_user.username != 'default':
 
                      ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='rss_icon')}
 
                      ${h.link_to(_('ATOM'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name,api_key=c.rhodecode_user.api_key),class_='atom_icon')}
 
                     %else:
 
                      ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.dbrepo.repo_name),class_='rss_icon')}
 
                      ${h.link_to(_('ATOM'),h.url('atom_feed_home',repo_name=c.dbrepo.repo_name),class_='atom_icon')}
 
                     %endif
 
                  </div>
 
                  %if c.rhodecode_user.username != 'default':
 
                      %if c.following:
 
                      <span id="follow_toggle" class="following tooltip" title="${_('Stop following this repository')}"
 
                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
 
                      </span>
 
                      %else:
 
                      <span id="follow_toggle" class="follow tooltip" title="${_('Start following this repository')}"
 
                            onclick="javascript:toggleFollowingRepo(this,${c.dbrepo.repo_id},'${str(h.get_token())}')">
 
                      </span>
 
                      %endif
 
                      <div style="float:right;padding:0px 0px 0px 0px">
 
                         <span class="reposize tooltip" title="${_('Click to show size of repository')}"
 
                            onclick="javascript:showRepoSize('repo_size','${c.dbrepo.repo_name}','${str(h.get_token())}')">
 
                         </span>
 
                         <span id="repo_size"></span>
 
                      </div>                                    
 
                      </div>
 
                  %endif:
 

	
 
                   ## locking icon
 
                    %if c.rhodecode_db_repo.enable_locking:
 
                      %if c.rhodecode_db_repo.locked[0]:
 
                        <span class="locking_locked tooltip" title="${_('Repository locked by %s') % h.person_by_id(c.rhodecode_db_repo.locked[0])}"></span>
 
                      %else:
 
                        <span class="locking_unlocked tooltip" title="${_('Repository unlocked')}"></span>
 
                      %endif
 
                    %endif
 
                 ##REPO TYPE
 
                 %if h.is_hg(c.dbrepo):
 
                   <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
 
                 %endif
 
                 %if h.is_git(c.dbrepo):
 
                   <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
 
                 %endif
 

	
 
                 ##PUBLIC/PRIVATE
 
                 %if c.dbrepo.private:
 
                    <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/>
 
                 %else:
 
                    <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/>
 
                 %endif
 

	
 
                  ##REPO NAME
 
                  <span class="repo_name" title="${_('Non changable ID %s') % c.dbrepo.repo_id}">${h.repo_link(c.dbrepo.groups_and_repo)}</span>
 

	
 
                  ##FORK
 
                  %if c.dbrepo.fork:
 
                    <div style="margin-top:5px;clear:both"">
 
                    <a href="${h.url('summary_home',repo_name=c.dbrepo.fork.repo_name)}"><img class="icon" alt="${_('public')}" title="${_('Fork of')} ${c.dbrepo.fork.repo_name}" src="${h.url('/images/icons/arrow_divide.png')}"/>
 
                        ${_('Fork of')} ${c.dbrepo.fork.repo_name}
 
                    </a>
 
                    </div>
 
                  %endif
 
                  ##REMOTE
 
                  %if c.dbrepo.clone_uri:
 
                    <div style="margin-top:5px;clear:both">
 
                    <a href="${h.url(str(h.hide_credentials(c.dbrepo.clone_uri)))}"><img class="icon" alt="${_('remote clone')}" title="${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}" src="${h.url('/images/icons/connect.png')}"/>
 
                        ${_('Clone from')} ${h.hide_credentials(c.dbrepo.clone_uri)}
 
                    </a>
 
                    </div>
 
                  %endif
 
              </div>
 
             </div>
 

	
 
             <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Description')}:</label>
 
              </div>
 
              %if c.visual.stylify_metatags:
 
                <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(h.desc_stylize(c.dbrepo.description))}</div>
 
              %else:
 
                <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.dbrepo.description)}</div>
 
              %endif
 
             </div>
 

	
 
             <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Contact')}:</label>
 
              </div>
 
              <div class="input ${summary(c.show_stats)}">
 
                  <div class="gravatar">
 
                      <img alt="gravatar" src="${h.gravatar_url(c.dbrepo.user.email)}"/>
 
                  </div>
 
                      ${_('Username')}: ${c.dbrepo.user.username}<br/>
 
                      ${_('Name')}: ${c.dbrepo.user.name} ${c.dbrepo.user.lastname}<br/>
 
                      ${_('Email')}: <a href="mailto:${c.dbrepo.user.email}">${c.dbrepo.user.email}</a>
 
              </div>
 
             </div>
 

	
 
             <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Clone url')}:</label>
 
              </div>
 
              <div class="input ${summary(c.show_stats)}">
 
                  <div  style="display:none" id="clone_by_name" class="ui-btn clone">${_('Show by Name')}</div>
 
                  <div id="clone_by_id" class="ui-btn clone">${_('Show by ID')}</div>
 
                  <input style="width:80%;margin-left:105px" type="text" id="clone_url" readonly="readonly" value="${c.clone_repo_url}"/>
 
                  <input style="display:none;width:80%;margin-left:105px" type="text" id="clone_url_id" readonly="readonly" value="${c.clone_repo_url_id}"/>
 
              </div>
 
             </div>
 

	
 
             <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Trending files')}:</label>
 
              </div>
 
              <div class="input ${summary(c.show_stats)}">
 
                %if c.show_stats:
 
                <div id="lang_stats"></div>
 
                %else:
 
                   ${_('Statistics are disabled for this repository')}
 
                   %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                        ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-btn")}
 
                   %endif
 
                %endif
 
              </div>
 
             </div>
 

	
 
             <div class="field">
 
              <div class="label-summary">
 
                  <label>${_('Download')}:</label>
 
              </div>
 
              <div class="input ${summary(c.show_stats)}">
 
                %if len(c.rhodecode_repo.revisions) == 0:
 
                  ${_('There are no downloads yet')}
 
                %elif c.enable_downloads is False:
 
                  ${_('Downloads are disabled for this repository')}
 
                    %if h.HasPermissionAll('hg.admin')('enable downloads on from summary'):
 
                        ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-btn")}
 
                    %endif
 
                %else:
 
                    ${h.select('download_options',c.rhodecode_repo.get_changeset().raw_id,c.download_options)}
 
                         <span id="${'zip_link'}">${h.link_to(_('Download as zip'), h.url('files_archive_home',repo_name=c.dbrepo.repo_name,fname='tip.zip'),class_="archive_icon ui-btn")}</span>
 
                    <span style="vertical-align: bottom">
 
                        <input id="archive_subrepos" type="checkbox" name="subrepos" />
 
                        <label for="archive_subrepos" class="tooltip" title="${h.tooltip(_('Check this to download archive with subrepos'))}" >${_('with subrepos')}</label>
 
                    </span>
 
                %endif
 
              </div>
 
             </div>
 
      </div>
 
    </div>
 
</div>
 

	
 
%if c.show_stats:
 
<div class="box box-right"  style="min-height:455px">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Commit activity by day / author')}</h5>
 
    </div>
 

	
 
    <div class="graph">
 
         <div style="padding:0 10px 10px 17px;">
 
         %if c.no_data:
 
           ${c.no_data_msg}
 
           %if h.HasPermissionAll('hg.admin')('enable stats on from summary'):
 
                ${h.link_to(_('enable'),h.url('edit_repo',repo_name=c.repo_name),class_="ui-btn")}
 
           %endif
 
        %else:
 
            ${_('Stats gathered: ')} ${c.stats_percentage}%
 
        %endif
 
        </div>
 
        <div id="commit_history" style="width:450px;height:300px;float:left"></div>
 
        <div style="clear: both;height: 10px"></div>
 
        <div id="overview" style="width:450px;height:100px;float:left"></div>
 

	
 
        <div id="legend_data" style="clear:both;margin-top:10px;">
 
            <div id="legend_container"></div>
 
            <div id="legend_choices">
 
                <table id="legend_choices_tables" class="noborder" style="font-size:smaller;color:#545454"></table>
 
            </div>
 
        </div>
 
    </div>
 
</div>
 
%endif
 

	
 
<div class="box">
 
    <div class="title">
 
        <div class="breadcrumbs">
 
        %if c.repo_changesets:
 
            ${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}
 
        %else:
 
            ${_('Quick start')}
 
         %endif
 
        </div>
 
    </div>
 
    <div class="table">
 
        <div id="shortlog_data">
 
            <%include file='../shortlog/shortlog_data.html'/>
 
        </div>
 
    </div>
 
</div>
 

	
 
%if c.readme_data:
 
<div id="readme" class="anchor">
 
<div class="box" style="background-color: #FAFAFA">
 
    <div class="title" title="${_("Readme file at revision '%s'" % c.rhodecode_db_repo.landing_rev)}">
 
        <div class="breadcrumbs">
 
            <a href="${h.url('files_home',repo_name=c.repo_name,revision='tip',f_path=c.readme_file)}">${c.readme_file}</a>
 
            <a class="permalink" href="#readme" title="${_('Permalink to this readme')}">&para;</a>
 
        </div>
 
    </div>
 
    <div class="readme">
 
      <div class="readme_box">
 
        ${c.readme_data|n}
 
      </div>
 
    </div>
 
</div>
 
</div>
 
%endif
 

	
 
<script type="text/javascript">
 
var clone_url = 'clone_url';
 
YUE.on(clone_url,'click',function(e){
 
    if(YUD.hasClass(clone_url,'selected')){
 
        return
 
    }
 
    else{
 
        YUD.addClass(clone_url,'selected');
 
        YUD.get(clone_url).select();
 
    }
 
})
 

	
 
YUE.on('clone_by_name','click',function(e){
 
    // show url by name and hide name button
 
    YUD.setStyle('clone_url','display','');
 
    YUD.setStyle('clone_by_name','display','none');
 

	
 
    // hide url by id and show name button
 
    YUD.setStyle('clone_by_id','display','');
 
    YUD.setStyle('clone_url_id','display','none');
 

	
 
})
 
YUE.on('clone_by_id','click',function(e){
 

	
 
    // show url by id and hide id button
 
    YUD.setStyle('clone_by_id','display','none');
 
    YUD.setStyle('clone_url_id','display','');
 

	
 
    // hide url by name and show id button
 
    YUD.setStyle('clone_by_name','display','');
 
    YUD.setStyle('clone_url','display','none');
 
})
 

	
 

	
 
var tmpl_links = {};
 
%for cnt,archive in enumerate(c.rhodecode_repo._get_archives()):
 
  tmpl_links["${archive['type']}"] = '${h.link_to('__NAME__', h.url('files_archive_home',repo_name=c.dbrepo.repo_name, fname='__CS__'+archive['extension'],subrepos='__SUB__'),class_='archive_icon ui-btn')}';
 
%endfor
 

	
 
YUE.on(['download_options','archive_subrepos'],'change',function(e){
 
   var sm = YUD.get('download_options');
 
   var new_cs = sm.options[sm.selectedIndex];
 

	
 
   for(k in tmpl_links){
 
       var s = YUD.get(k+'_link');
 
       if(s){
 
         var title_tmpl = "${_('Download %s as %s') % ('__CS_NAME__','__CS_EXT__')}";
 
         title_tmpl= title_tmpl.replace('__CS_NAME__',new_cs.text);
 
         title_tmpl = title_tmpl.replace('__CS_EXT__',k);
 

	
 
         var url = tmpl_links[k].replace('__CS__',new_cs.value);
 
         var subrepos = YUD.get('archive_subrepos').checked;
 
         url = url.replace('__SUB__',subrepos);
 
         url = url.replace('__NAME__',title_tmpl);
 
         s.innerHTML = url
 
       }
 
   }
 
});
 
</script>
 
%if c.show_stats:
 
<script type="text/javascript">
 
var data = ${c.trending_languages|n};
 
var total = 0;
 
var no_data = true;
 
var tbl = document.createElement('table');
 
tbl.setAttribute('class','trending_language_tbl');
 
var cnt = 0;
 
for (var i=0;i<data.length;i++){
 
    total+= data[i][1].count;
 
}
 
for (var i=0;i<data.length;i++){
 
    cnt += 1;
 
    no_data = false;
 

	
 
    var hide = cnt>2;
 
    var tr = document.createElement('tr');
 
    if (hide){
 
        tr.setAttribute('style','display:none');
 
        tr.setAttribute('class','stats_hidden');
 
    }
 
    var k = data[i][0];
 
    var obj = data[i][1];
 
    var percentage = Math.round((obj.count/total*100),2);
 

	
 
    var td1 = document.createElement('td');
 
    td1.width = 150;
 
    var trending_language_label = document.createElement('div');
 
    trending_language_label.innerHTML = obj.desc+" ("+k+")";
 
    td1.appendChild(trending_language_label);
 

	
 
    var td2 = document.createElement('td');
 
    td2.setAttribute('style','padding-right:14px !important');
 
    var trending_language = document.createElement('div');
 
    var nr_files = obj.count+" ${_('files')}";
 

	
 
    trending_language.title = k+" "+nr_files;
 

	
 
    if (percentage>22){
 
        trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";
 
    }
 
    else{
 
        trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
 
    }
 

	
 
    trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
 
    trending_language.style.width=percentage+"%";
 
    td2.appendChild(trending_language);
 

	
 
    tr.appendChild(td1);
 
    tr.appendChild(td2);
 
    tbl.appendChild(tr);
 
    if(cnt == 3){
 
        var show_more = document.createElement('tr');
 
        var td = document.createElement('td');
 
        lnk = document.createElement('a');
 

	
 
        lnk.href='#';
 
        lnk.innerHTML = "${_('show more')}";
 
        lnk.id='code_stats_show_more';
 
        td.appendChild(lnk);
 

	
 
        show_more.appendChild(td);
 
        show_more.appendChild(document.createElement('td'));
 
        tbl.appendChild(show_more);
 
    }
 

	
 
}
 

	
 
YUD.get('lang_stats').appendChild(tbl);
 
YUE.on('code_stats_show_more','click',function(){
 
    l = YUD.getElementsByClassName('stats_hidden')
 
    for (e in l){
 
        YUD.setStyle(l[e],'display','');
 
    };
 
    YUD.setStyle(YUD.get('code_stats_show_more'),
 
            'display','none');
 
});
 
</script>
 
<script type="text/javascript">
 
/**
 
 * Plots summary graph
 
 *
 
 * @class SummaryPlot
 
 * @param {from} initial from for detailed graph
 
 * @param {to} initial to for detailed graph
 
 * @param {dataset}
 
 * @param {overview_dataset}
 
 */
 
function SummaryPlot(from,to,dataset,overview_dataset) {
 
    var initial_ranges = {
 
        "xaxis":{
 
            "from":from,
 
            "to":to,
 
        },
 
    };
 
    var dataset = dataset;
 
    var overview_dataset = [overview_dataset];
 
    var choiceContainer = YUD.get("legend_choices");
 
    var choiceContainerTable = YUD.get("legend_choices_tables");
 
    var plotContainer = YUD.get('commit_history');
 
    var overviewContainer = YUD.get('overview');
 

	
 
    var plot_options = {
 
        bars: {show:true,align:'center',lineWidth:4},
 
        legend: {show:true, container:"legend_container"},
 
        points: {show:true,radius:0,fill:false},
 
        yaxis: {tickDecimals:0,},
 
        xaxis: {
 
            mode: "time",
 
            timeformat: "%d/%m",
 
            min:from,
 
            max:to,
 
        },
 
        grid: {
 
            hoverable: true,
 
            clickable: true,
 
            autoHighlight:true,
 
            color: "#999"
 
        },
 
        //selection: {mode: "x"}
 
    };
 
    var overview_options = {
 
        legend:{show:false},
 
        bars: {show:true,barWidth: 2,},
 
        shadowSize: 0,
 
        xaxis: {mode: "time", timeformat: "%d/%m/%y",},
 
        yaxis: {ticks: 3, min: 0,tickDecimals:0,},
 
        grid: {color: "#999",},
 
        selection: {mode: "x"}
 
    };
 

	
 
    /**
 
    *get dummy data needed in few places
 
    */
 
    function getDummyData(label){
 
        return {"label":label,
 
         "data":[{"time":0,
 
             "commits":0,
 
                 "added":0,
 
                 "changed":0,
 
                 "removed":0,
 
            }],
 
            "schema":["commits"],
 
            "color":'#ffffff',
 
        }
 
    }
 

	
 
    /**
 
     * generate checkboxes accordindly to data
 
     * @param keys
 
     * @returns
 
     */
 
    function generateCheckboxes(data) {
 
        //append checkboxes
 
        var i = 0;
 
        choiceContainerTable.innerHTML = '';
 
        for(var pos in data) {
 

	
 
            data[pos].color = i;
 
            i++;
 
            if(data[pos].label != ''){
 
                choiceContainerTable.innerHTML +=
 
                    '<tr><td><input type="checkbox" id="id_user_{0}" name="{0}" checked="checked" /> \
 
                     <label for="id_user_{0}">{0}</label></td></tr>'.format(data[pos].label);
 
            }
 
        }
 
    }
 

	
 
    /**
 
     * ToolTip show
 
     */
 
    function showTooltip(x, y, contents) {
 
        var div=document.getElementById('tooltip');
 
        if(!div) {
 
            div = document.createElement('div');
 
            div.id="tooltip";
 
            div.style.position="absolute";
 
            div.style.border='1px solid #fdd';
 
            div.style.padding='2px';
 
            div.style.backgroundColor='#fee';
 
            document.body.appendChild(div);
 
        }
 
        YUD.setStyle(div, 'opacity', 0);
 
        div.innerHTML = contents;
 
        div.style.top=(y + 5) + "px";
 
        div.style.left=(x + 5) + "px";
 

	
 
        var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
 
        anim.animate();
 
    }
 

	
 
    /**
 
     * This function will detect if selected period has some changesets
 
       for this user if it does this data is then pushed for displaying
 
       Additionally it will only display users that are selected by the checkbox
 
    */
 
    function getDataAccordingToRanges(ranges) {
 

	
 
        var data = [];
 
        var new_dataset = {};
 
        var keys = [];
 
        var max_commits = 0;
 
        for(var key in dataset){
 

	
 
            for(var ds in dataset[key].data){
 
                commit_data = dataset[key].data[ds];
 
                if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
 

	
 
                    if(new_dataset[key] === undefined){
 
                        new_dataset[key] = {data:[],schema:["commits"],label:key};
 
                    }
 
                    new_dataset[key].data.push(commit_data);
 
                }
 
            }
 
            if (new_dataset[key] !== undefined){
 
                data.push(new_dataset[key]);
 
            }
 
        }
 

	
 
        if (data.length > 0){
 
            return data;
 
        }
 
        else{
 
            //just return dummy data for graph to plot itself
 
            return [getDummyData('')];
 
        }
 
    }
 

	
 
    /**
 
    * redraw using new checkbox data
 
    */
 
    function plotchoiced(e,args){
 
        var cur_data = args[0];
 
        var cur_ranges = args[1];
 

	
 
        var new_data = [];
 
        var inputs = choiceContainer.getElementsByTagName("input");
 

	
 
        //show only checked labels
 
        for(var i=0; i<inputs.length; i++) {
 
            var checkbox_key = inputs[i].name;
 

	
 
            if(inputs[i].checked){
 
                for(var d in cur_data){
 
                    if(cur_data[d].label == checkbox_key){
 
                        new_data.push(cur_data[d]);
 
                    }
 
                }
 
            }
 
            else{
 
                //push dummy data to not hide the label
 
                new_data.push(getDummyData(checkbox_key));
 
            }
 
        }
 

	
 
        var new_options = YAHOO.lang.merge(plot_options, {
 
            xaxis: {
 
                min: cur_ranges.xaxis.from,
 
                max: cur_ranges.xaxis.to,
 
                mode:"time",
 
                timeformat: "%d/%m",
 
            },
 
        });
 
        if (!new_data){
 
            new_data = [[0,1]];
 
        }
 
        // do the zooming
 
       plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
 

	
 
       plot.subscribe("plotselected", plotselected);
 

	
 
       //resubscribe plothover
 
       plot.subscribe("plothover", plothover);
 

	
 
       // don't fire event on the overview to prevent eternal loop
 
       overview.setSelection(cur_ranges, true);
 

	
 
    }
 

	
 
    /**
 
     * plot only selected items from overview
 
     * @param ranges
 
     * @returns
 
     */
 
    function plotselected(ranges,cur_data) {
 
        //updates the data for new plot
 
        var data = getDataAccordingToRanges(ranges);
 
        generateCheckboxes(data);
 

	
 
        var new_options = YAHOO.lang.merge(plot_options, {
 
            xaxis: {
 
                min: ranges.xaxis.from,
 
                max: ranges.xaxis.to,
 
                mode:"time",
 
                timeformat: "%d/%m",
 
            },
 
        });
 
        // do the zooming
 
        plot = YAHOO.widget.Flot(plotContainer, data, new_options);
 

	
 
        plot.subscribe("plotselected", plotselected);
 

	
 
        //resubscribe plothover
 
        plot.subscribe("plothover", plothover);
 

	
 
        // don't fire event on the overview to prevent eternal loop
 
        overview.setSelection(ranges, true);
 

	
 
        //resubscribe choiced
 
        YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
 
    }
 

	
 
    var previousPoint = null;
 

	
 
    function plothover(o) {
 
        var pos = o.pos;
 
        var item = o.item;
 

	
 
        //YUD.get("x").innerHTML = pos.x.toFixed(2);
 
        //YUD.get("y").innerHTML = pos.y.toFixed(2);
 
        if (item) {
 
            if (previousPoint != item.datapoint) {
 
                previousPoint = item.datapoint;
 

	
 
                var tooltip = YUD.get("tooltip");
 
                if(tooltip) {
 
                      tooltip.parentNode.removeChild(tooltip);
 
                }
 
                var x = item.datapoint.x.toFixed(2);
 
                var y = item.datapoint.y.toFixed(2);
 

	
 
                if (!item.series.label){
 
                    item.series.label = 'commits';
 
                }
 
                var d = new Date(x*1000);
 
                var fd = d.toDateString()
 
                var nr_commits = parseInt(y);
 

	
 
                var cur_data = dataset[item.series.label].data[item.dataIndex];
 
                var added = cur_data.added;
 
                var changed = cur_data.changed;
 
                var removed = cur_data.removed;
 

	
 
                var nr_commits_suffix = " ${_('commits')} ";
 
                var added_suffix = " ${_('files added')} ";
 
                var changed_suffix = " ${_('files changed')} ";
 
                var removed_suffix = " ${_('files removed')} ";
 

	
 

	
 
                if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
 
                if(added==1){added_suffix=" ${_('file added')} ";}
 
                if(changed==1){changed_suffix=" ${_('file changed')} ";}
 
                if(removed==1){removed_suffix=" ${_('file removed')} ";}
 

	
 
                showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
 
                         +'<br/>'+
 
                         nr_commits + nr_commits_suffix+'<br/>'+
 
                         added + added_suffix +'<br/>'+
 
                         changed + changed_suffix + '<br/>'+
 
                         removed + removed_suffix + '<br/>');
 
            }
 
        }
 
        else {
 
              var tooltip = YUD.get("tooltip");
 

	
 
              if(tooltip) {
 
                    tooltip.parentNode.removeChild(tooltip);
 
              }
 
            previousPoint = null;
 
        }
 
    }
 

	
 
    /**
 
     * MAIN EXECUTION
 
     */
 

	
 
    var data = getDataAccordingToRanges(initial_ranges);
 
    generateCheckboxes(data);
 

	
 
    //main plot
 
    var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
 

	
 
    //overview
 
    var overview = YAHOO.widget.Flot(overviewContainer,
 
            overview_dataset, overview_options);
 

	
 
    //show initial selection on overview
 
    overview.setSelection(initial_ranges);
 

	
 
    plot.subscribe("plotselected", plotselected);
 
    plot.subscribe("plothover", plothover)
 

	
 
    overview.subscribe("plotselected", function (ranges) {
 
        plot.setSelection(ranges);
 
    });
 

	
 
    // user choices on overview
 
    YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
 
}
 
    SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});
 
</script>
 
%endif
 

	
 
</%def>
0 comments (0 inline, 0 general)