changeset 1861:3f5be4dbbd57 beta

merge upstream
author Aras Pranckevicius <aras@unity3d.com>
date Sun, 08 Jan 2012 12:18:16 +0200
parents 1f06cd49cb3e (current diff) 349a0ca30a75 (diff)
children 2a159aa3ed2d
files docs/usage/api_key_access.rst rhodecode/public/css/style.css rhodecode/templates/changelog/changelog.html rhodecode/templates/changeset/changeset.html rhodecode/templates/changeset/diff_block.html
diffstat 25 files changed, 422 insertions(+), 206 deletions(-) [+]
line wrap: on
line diff
--- a/README.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/README.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -1,6 +1,6 @@
-=================================================
-Welcome to RhodeCode (RhodiumCode) documentation!
-=================================================
+========================
+RhodeCode documentation!
+========================
 
 ``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_ 
 with a built in push/pull server and full text search.
@@ -102,7 +102,6 @@
 - pull requests and web based merges
 - per line file history
 - SSH based authentication with server side key management
-- Redmine and other bugtrackers integration
 - Commit based built in wiki system
 - More statistics and graph (global annotation + some more statistics)
 - Other advancements as development continues (or you can of course make 
--- a/development.ini	Sat Jan 07 21:44:18 2012 +0200
+++ b/development.ini	Sun Jan 08 12:18:16 2012 +0200
@@ -58,13 +58,34 @@
 proxypass_auth_enabled = false
 
 ## overwrite schema of clone url
-# available vars:
-# scheme - http/https
-# user - current user
-# pass - password 
-# netloc - network location
-# path - usually repo_name
-# clone_uri = {scheme}://{user}{pass}{netloc}{path}
+## available vars:
+## scheme - http/https
+## user - current user
+## pass - password 
+## netloc - network location
+## path - usually repo_name
+
+#clone_uri = {scheme}://{user}{pass}{netloc}{path}
+
+## issue tracking mapping for commits messages
+## uncomment url_pat, issue_server, issue_prefix to enable
+
+
+## pattern to get the issues from commit messages
+## default one used here is #1234
+
+#url_pat = (?:^#|\s#)(\w+)
+
+## server url to the issue, each {id} will be replaced with id
+## fetched from the regex
+
+#issue_server = https://myissueserver.com/issue/{id}
+
+## prefix to add to link to indicate it's an url
+## #314 will be replaced by <issue_prefix><id>
+
+#issue_prefix = #
+
 
 ####################################
 ###        CELERY CONFIG        ####
--- a/docs/api/api.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/docs/api/api.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -10,6 +10,8 @@
 with JSON protocol both ways. An url to send API request in RhodeCode is
 <your_server>/_admin/api
 
+API ACCESS FOR WEB VIEWS
+++++++++++++++++++++++++
 
 API access can also be turned on for each view decorated with `@LoginRequired`
 decorator. To enable API access simple change standard login decorator into
@@ -18,6 +20,9 @@
 enabled on RSS/ATOM feed views.
 
 
+API ACCESS
+++++++++++
+
 All clients are required to send JSON-RPC spec JSON data::
 
     {   
@@ -69,15 +74,47 @@
     api_key : "<api_key>"
     method :  "pull"
     args :    {
-                "repo" : "<repo_name>"
+                "repo_name" : "<reponame>"
               }
 
 OUTPUT::
 
-    result : "Pulled from <repo_name>"
+    result : "Pulled from <reponame>"
     error :  null
 
 
+get_user
+--------
+
+Get's an user by username, Returns empty result if user is not found.
+This command can be executed only using api_key belonging to user with admin 
+rights.
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_user"
+    args :    { 
+                "username" : "<username>"
+              }
+
+OUTPUT::
+
+    result: None if user does not exist or 
+            {
+                "id" :       "<id>",
+                "username" : "<username>",
+                "firstname": "<firstname>",
+                "lastname" : "<lastname>",
+                "email" :    "<email>",
+                "active" :   "<bool>",
+                "admin" :    "<bool>",
+                "ldap" :     "<ldap_dn>"
+            }
+
+    error:  null
+
+
 get_users
 ---------
 
@@ -131,46 +168,11 @@
 OUTPUT::
 
     result: {
+              "id" : "<new_user_id>",
               "msg" : "created new user <username>"
             }
     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::
-
-    api_key : "<api_key>"
-    method :  "get_users_groups"
-    args :    { }
-
-OUTPUT::
-
-    result : [
-               {
-                 "id" :       "<id>",
-                 "name" :     "<name>",
-                 "active":    "<bool>",
-                 "members" :  [
-	    	                    {
-	    	                      "id" :       "<userid>",
-	                              "username" : "<username>",
-	                              "firstname": "<firstname>",
-	                              "lastname" : "<lastname>",
-	                              "email" :    "<email>",
-	                              "active" :   "<bool>",
-	                              "admin" :    "<bool>",
-	                              "ldap" :     "<ldap_dn>"
-	                            },
-	    	                    …
-	                          ]
-	            }
-              ]
-    error : null
-
 get_users_group
 ---------------
 
@@ -189,24 +191,61 @@
 
     result : None if group not exist
              {
-               "id" :       "<id>",
-               "name" :     "<name>",
-               "active":    "<bool>",
+               "id" :         "<id>",
+               "group_name" : "<groupname>",
+               "active":      "<bool>",
                "members" :  [
-	    	                  { "id" :       "<userid>",
-	                            "username" : "<username>",
-	                            "firstname": "<firstname>",
-	                            "lastname" : "<lastname>",
-	                            "email" :    "<email>",
-	                            "active" :   "<bool>",
-	                            "admin" :    "<bool>",
-	                            "ldap" :     "<ldap_dn>"
-	                          },
-	    	                  …
-	                        ]
+                              { "id" :       "<userid>",
+                                "username" : "<username>",
+                                "firstname": "<firstname>",
+                                "lastname" : "<lastname>",
+                                "email" :    "<email>",
+                                "active" :   "<bool>",
+                                "admin" :    "<bool>",
+                                "ldap" :     "<ldap_dn>"
+                              },
+                              …
+                            ]
              }
     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::
+
+    api_key : "<api_key>"
+    method :  "get_users_groups"
+    args :    { }
+
+OUTPUT::
+
+    result : [
+               {
+                 "id" :         "<id>",
+                 "group_name" : "<groupname>",
+                 "active":      "<bool>",
+                 "members" :  [
+	    	                    {
+	    	                      "id" :       "<userid>",
+	                              "username" : "<username>",
+	                              "firstname": "<firstname>",
+	                              "lastname" : "<lastname>",
+	                              "email" :    "<email>",
+	                              "active" :   "<bool>",
+	                              "admin" :    "<bool>",
+	                              "ldap" :     "<ldap_dn>"
+	                            },
+	    	                    …
+	                          ]
+	            }
+              ]
+    error : null
+
+
 create_users_group
 ------------------
 
@@ -218,7 +257,7 @@
     api_key : "<api_key>"
     method :  "create_users_group"
     args:     {
-                "name":  "<name>",
+                "group_name":  "<groupname>",
                 "active":"<bool> = True"
               }
 
@@ -226,7 +265,7 @@
 
     result: {
               "id":  "<newusersgroupid>",
-              "msg": "created new users group <name>"
+              "msg": "created new users group <groupname>"
             }
     error:  null
 
@@ -253,6 +292,51 @@
             }
     error:  null
 
+get_repo
+--------
+
+Gets an existing repository. This command can be executed only using api_key
+belonging to user with admin rights
+
+INPUT::
+
+    api_key : "<api_key>"
+    method :  "get_repo"
+    args:     {
+                "repo_name" : "<reponame>"
+              }
+
+OUTPUT::
+
+    result: None if repository does not exist or
+            {
+                "id" :          "<id>",
+                "repo_name" :   "<reponame>"
+                "type" :        "<type>",
+                "description" : "<description>",
+                "members" :     [
+                                  { "id" :         "<userid>",
+                                    "username" :   "<username>",
+                                    "firstname":   "<firstname>",
+                                    "lastname" :   "<lastname>",
+                                    "email" :      "<email>",
+                                    "active" :     "<bool>",
+                                    "admin" :      "<bool>",
+                                    "ldap" :       "<ldap_dn>",
+                                    "permission" : "repository.(read|write|admin)"
+                                  },
+                                  …
+                                  {
+                                    "id" :       "<usersgroupid>",
+                                    "name" :     "<usersgroupname>",
+                                    "active":    "<bool>",
+                                    "permission" : "repository.(read|write|admin)"
+                                  },
+                                  …
+                                ]
+            }
+    error:  null
+
 get_repos
 ---------
 
@@ -270,7 +354,7 @@
     result: [
               {
                 "id" :          "<id>",
-                "name" :        "<name>"
+                "repo_name" :   "<reponame>"
                 "type" :        "<type>",
                 "description" : "<description>"
               },
@@ -278,57 +362,13 @@
             ]
     error:  null
 
-get_repo
---------
-
-Gets an existing repository. This command can be executed only using api_key
-belonging to user with admin rights
-
-INPUT::
-
-    api_key : "<api_key>"
-    method :  "get_repo"
-    args:     {
-                "name" : "<name>"
-              }
-
-OUTPUT::
-
-    result: None if repository not exist
-            {
-                "id" :          "<id>",
-                "name" :        "<name>"
-                "type" :        "<type>",
-                "description" : "<description>",
-                "members" :     [
-                                  { "id" :         "<userid>",
-	                                "username" :   "<username>",
-	                                "firstname":   "<firstname>",
-	                                "lastname" :   "<lastname>",
-	                                "email" :      "<email>",
-	                                "active" :     "<bool>",
-	                                "admin" :      "<bool>",
-	                                "ldap" :       "<ldap_dn>",
-	                                "permission" : "repository.(read|write|admin)"
-	                              },
-                                  …
-                                  {
-                                    "id" :       "<usersgroupid>",
-                                    "name" :     "<usersgroupname>",
-                                    "active":    "<bool>",
-                                    "permission" : "repository.(read|write|admin)"
-                                  },
-                                  …
-                                ]
-            }
-    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 
+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::
@@ -336,7 +376,7 @@
     api_key : "<api_key>"
     method :  "get_repo_nodes"
     args:     {
-                "repo_name" : "<name>",
+                "repo_name" : "<reponame>",
                 "revision"  : "<revision>",
                 "root_path" : "<root_path>",
                 "ret_type"  : "<ret_type>" = 'all'
@@ -369,7 +409,7 @@
     api_key : "<api_key>"
     method :  "create_repo"
     args:     {
-                "name" :        "<name>",
+                "repo_name" :   "<reponame>",
                 "owner_name" :  "<ownername>",
                 "description" : "<description> = ''",
                 "repo_type" :   "<type> = 'hg'",
@@ -378,7 +418,10 @@
 
 OUTPUT::
 
-    result: None
+    result: {
+                "id": "<newrepoid>",
+                "msg": "Created new repository <reponame>",
+            }
     error:  null
 
 add_user_to_repo
@@ -394,13 +437,15 @@
     method :  "add_user_to_repo"
     args:     {
                 "repo_name" :  "<reponame>",
-                "username" :  "<username>",
+                "username" :   "<username>",
                 "perm" :       "(None|repository.(read|write|admin))",
               }
 
 OUTPUT::
 
-    result: None
+    result: {
+                "msg" : "Added perm: <perm> for <username> in repo: <reponame>"
+            }
     error:  null
 
 add_users_group_to_repo
@@ -416,6 +461,12 @@
     method :  "add_users_group_to_repo"
     args:     {
                 "repo_name" :  "<reponame>",
-                "group_name" :  "<groupname>",
+                "group_name" : "<groupname>",
                 "perm" :       "(None|repository.(read|write|admin))",
-              }
\ No newline at end of file
+              }
+OUTPUT::
+    
+    result: {
+                "msg" : Added perm: <perm> for <groupname> in repo: <reponame>"
+            }
+
--- a/docs/api/index.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/docs/api/index.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -1,4 +1,4 @@
-.. _api:
+.. _indexapi:
 
 API Reference
 =============
--- a/docs/api/models.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/docs/api/models.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -6,14 +6,29 @@
 .. automodule:: rhodecode.model
    :members:
    
+.. automodule:: rhodecode.model.comment
+   :members:
+  
+.. automodule:: rhodecode.model.notification
+   :members:   
+
 .. automodule:: rhodecode.model.permission
    :members:
-  
+
+.. automodule:: rhodecode.model.repo_permission
+   :members:      
+
 .. automodule:: rhodecode.model.repo
    :members:   
 
+.. automodule:: rhodecode.model.repos_group
+   :members:
+   
 .. automodule:: rhodecode.model.scm
    :members:
-
+   
 .. automodule:: rhodecode.model.user
    :members:      
+   
+.. automodule:: rhodecode.model.users_group
+   :members:   
\ No newline at end of file
--- a/docs/changelog.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/docs/changelog.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -33,7 +33,9 @@
 - implements #330 api method for listing nodes ar particular revision
 - fixed #331 RhodeCode mangles repository names if the a repository group 
   contains the "full path" to the repositories
-  
+- #73 added linking issues in commit messages to choosen issue tracker url
+  based on user defined regular expression
+    
 fixes
 -----
 
--- a/docs/index.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/docs/index.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -2,8 +2,8 @@
 
 .. include:: ./../README.rst
 
-Documentation
--------------
+Users Guide
+-----------
 
 **Installation:**
 
@@ -23,7 +23,6 @@
    usage/enable_git
    usage/statistics
    usage/backup
-   usage/api_key_access
    
 **Develop**
 
@@ -36,7 +35,7 @@
 **API**
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    api/index
    
--- a/docs/setup.rst	Sat Jan 07 21:44:18 2012 +0200
+++ b/docs/setup.rst	Sun Jan 08 12:18:16 2012 +0200
@@ -425,7 +425,25 @@
    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 = https://myissueserver.com/issue/{id}
+    issue_prefix = #
+
+`url_pat` is the regular expression that will match issues, default given regex
+will match issues in format of #<number> eg. #300. 
+Matched issues will be replace with the `issue_server` url replacing {id} with
+id fetched from regex. 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/issue/300">ISSUE-300</a>`  
 
 Hook management
 ---------------
--- a/docs/usage/api_key_access.rst	Sat Jan 07 21:44:18 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-.. _api_key_access:
-
-Access to RhodeCode via API KEY
-===============================
-
-Starting from version 1.2 rss/atom feeds and journal feeds
-can be accessed via **api_key**. This unique key is automatically generated for
-each user in RhodeCode application. Using this key it is possible to access 
-feeds without having to log in. When user changes his password a new API KEY
-is generated for him automatically. You can check your API KEY in account 
-settings page. 
\ No newline at end of file
--- a/production.ini	Sat Jan 07 21:44:18 2012 +0200
+++ b/production.ini	Sun Jan 08 12:18:16 2012 +0200
@@ -58,13 +58,34 @@
 proxypass_auth_enabled = false
 
 ## overwrite schema of clone url
-# available vars:
-# scheme - http/https
-# user - current user
-# pass - password 
-# netloc - network location
-# path - usually repo_name
-# clone_uri = {scheme}://{user}{pass}{netloc}{path}
+## available vars:
+## scheme - http/https
+## user - current user
+## pass - password 
+## netloc - network location
+## path - usually repo_name
+
+#clone_uri = {scheme}://{user}{pass}{netloc}{path}
+
+## issue tracking mapping for commits messages
+## uncomment url_pat, issue_server, issue_prefix to enable
+
+
+## pattern to get the issues from commit messages
+## default one used here is #1234
+
+#url_pat = (?:^#|\s#)(\w+)
+
+## server url to the issue, each {id} will be replaced with id
+## fetched from the regex
+
+#issue_server = https://myissueserver.com/issue/{id}
+
+## prefix to add to link to indicate it's an url
+## #314 will be replaced by <issue_prefix><id>
+
+#issue_prefix = #
+
 
 ####################################
 ###        CELERY CONFIG        ####
--- a/rhodecode/config/deployment.ini_tmpl	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/config/deployment.ini_tmpl	Sun Jan 08 12:18:16 2012 +0200
@@ -58,14 +58,35 @@
 proxypass_auth_enabled = false
 
 ## overwrite schema of clone url
-# available vars:
-# scheme - http/https
-# user - current user
-# pass - password 
-# netloc - network location
-# path - usually repo_name
+## available vars:
+## scheme - http/https
+## user - current user
+## pass - password 
+## netloc - network location
+## path - usually repo_name
+
 # clone_uri = {scheme}://{user}{pass}{netloc}{path}
 
+## issue tracking mapping for commits messages
+## uncomment url_pat, issue_server, issue_prefix to enable
+
+
+## pattern to get the issues from commit messages
+## default one used here is #1234
+
+#url_pat = (?:^#|\s#)(\w+)
+
+## server url to the issue, each {id} will be replaced with id
+## fetched from the regex
+
+#issue_server = https://myissueserver.com/issue/{id}
+
+## prefix to add to link to indicate it's an url
+## #314 will be replaced by <issue_prefix><id>
+
+#issue_prefix = #
+
+
 ####################################
 ###        CELERY CONFIG        ####
 ####################################
--- a/rhodecode/controllers/api/api.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/controllers/api/api.py	Sun Jan 08 12:18:16 2012 +0200
@@ -64,23 +64,23 @@
     """
 
     @HasPermissionAllDecorator('hg.admin')
-    def pull(self, apiuser, repo):
+    def pull(self, apiuser, repo_name):
         """
         Dispatch pull action on given repo
 
 
         :param user:
-        :param repo:
+        :param repo_name:
         """
 
-        if Repository.is_valid(repo) is False:
-            raise JSONRPCError('Unknown repo "%s"' % repo)
+        if Repository.is_valid(repo_name) is False:
+            raise JSONRPCError('Unknown repo "%s"' % repo_name)
 
         try:
-            ScmModel().pull_changes(repo, self.rhodecode_user.username)
-            return 'Pulled from %s' % repo
+            ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
+            return 'Pulled from %s' % repo_name
         except Exception:
-            raise JSONRPCError('Unable to pull changes from "%s"' % repo)
+            raise JSONRPCError('Unable to pull changes from "%s"' % repo_name)
 
     @HasPermissionAllDecorator('hg.admin')
     def get_user(self, apiuser, username):
@@ -151,10 +151,15 @@
             raise JSONRPCError("user %s already exist" % username)
 
         try:
-            UserModel().create_or_update(username, password, email, firstname,
-                                         lastname, active, admin, ldap_dn)
+            usr = UserModel().create_or_update(
+                username, password, email, firstname,
+                lastname, active, admin, ldap_dn
+            )
             Session.commit()
-            return dict(msg='created new user %s' % username)
+            return dict(
+                id=usr.user_id,
+                msg='created new user %s' % username
+            )
         except Exception:
             log.error(traceback.format_exc())
             raise JSONRPCError('failed to create user %s' % username)
@@ -185,7 +190,7 @@
                             ldap=user.ldap_dn))
 
         return dict(id=users_group.users_group_id,
-                    name=users_group.users_group_name,
+                    group_name=users_group.users_group_name,
                     active=users_group.users_group_active,
                     members=members)
 
@@ -212,31 +217,31 @@
                                 ldap=user.ldap_dn))
 
             result.append(dict(id=users_group.users_group_id,
-                                name=users_group.users_group_name,
+                                group_name=users_group.users_group_name,
                                 active=users_group.users_group_active,
                                 members=members))
         return result
 
     @HasPermissionAllDecorator('hg.admin')
-    def create_users_group(self, apiuser, name, active=True):
+    def create_users_group(self, apiuser, group_name, active=True):
         """
         Creates an new usergroup
 
-        :param name:
+        :param group_name:
         :param active:
         """
 
-        if self.get_users_group(apiuser, name):
-            raise JSONRPCError("users group %s already exist" % name)
+        if self.get_users_group(apiuser, group_name):
+            raise JSONRPCError("users group %s already exist" % group_name)
 
         try:
-            ug = UsersGroupModel().create(name=name, active=active)
+            ug = UsersGroupModel().create(name=group_name, active=active)
             Session.commit()
             return dict(id=ug.users_group_id,
-                        msg='created new users group %s' % name)
+                        msg='created new users group %s' % group_name)
         except Exception:
             log.error(traceback.format_exc())
-            raise JSONRPCError('failed to create group %s' % name)
+            raise JSONRPCError('failed to create group %s' % group_name)
 
     @HasPermissionAllDecorator('hg.admin')
     def add_user_to_users_group(self, apiuser, group_name, username):
@@ -312,7 +317,7 @@
 
         return dict(
             id=repo.repo_id,
-            name=repo.repo_name,
+            repo_name=repo.repo_name,
             type=repo.repo_type,
             description=repo.description,
             members=members
@@ -331,7 +336,7 @@
             result.append(
                 dict(
                     id=repository.repo_id,
-                    name=repository.repo_name,
+                    repo_name=repository.repo_name,
                     type=repository.repo_type,
                     description=repository.description
                 )
@@ -367,13 +372,13 @@
             raise JSONRPCError(e)
 
     @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
-    def create_repo(self, apiuser, name, owner_name, description='',
+    def create_repo(self, apiuser, repo_name, owner_name, description='',
                     repo_type='hg', private=False):
         """
         Create a repository
 
         :param apiuser:
-        :param name:
+        :param repo_name:
         :param description:
         :param type:
         :param private:
@@ -386,10 +391,10 @@
             except NoResultFound:
                 raise JSONRPCError('unknown user %s' % owner)
 
-            if self.get_repo(apiuser, name):
-                raise JSONRPCError("repo %s already exist" % name)
+            if Repository.get_by_repo_name(repo_name):
+                raise JSONRPCError("repo %s already exist" % repo_name)
 
-            groups = name.split('/')
+            groups = repo_name.split('/')
             real_name = groups[-1]
             groups = groups[:-1]
             parent_id = None
@@ -405,10 +410,10 @@
                     )
                 parent_id = group.group_id
 
-            RepoModel().create(
+            repo = RepoModel().create(
                 dict(
                     repo_name=real_name,
-                    repo_name_full=name,
+                    repo_name_full=repo_name,
                     description=description,
                     private=private,
                     repo_type=repo_type,
@@ -418,9 +423,15 @@
                 owner
             )
             Session.commit()
+
+            return dict(
+                id=repo.repo_id,
+                msg="Created new repository %s" % repo.repo_name
+            )
+
         except Exception:
             log.error(traceback.format_exc())
-            raise JSONRPCError('failed to create repository %s' % name)
+            raise JSONRPCError('failed to create repository %s' % repo_name)
 
     @HasPermissionAnyDecorator('hg.admin')
     def add_user_to_repo(self, apiuser, repo_name, username, perm):
--- a/rhodecode/lib/db_manage.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/db_manage.py	Sun Jan 08 12:18:16 2012 +0200
@@ -97,6 +97,13 @@
         from rhodecode.lib.dbmigrate.migrate.exceptions import \
             DatabaseNotControlledError
 
+        if 'sqlite' in self.dburi:
+            print (
+               '********************** WARNING **********************\n'
+               'Make sure your version of sqlite is at least 3.7.X.  \n'
+               'Earlier versions are known to fail on some migrations\n'
+               '*****************************************************\n'
+            )
         upgrade = ask_ok('You are about to perform database upgrade, make '
                          'sure You backed up your database before. '
                          'Continue ? [y/n]')
@@ -161,6 +168,9 @@
                 print ('Adding ldap defaults')
                 self.klass.create_ldap_options(skip_existing=True)
 
+            def step_4(self):
+                print ('TODO:')
+
         upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
 
         # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
--- a/rhodecode/lib/helpers.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/helpers.py	Sun Jan 08 12:18:16 2012 +0200
@@ -8,6 +8,7 @@
 import StringIO
 import urllib
 import math
+import logging
 
 from datetime import datetime
 from pygments.formatters.html import HtmlFormatter
@@ -41,6 +42,8 @@
 from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
 from rhodecode.lib.markup_renderer import MarkupRenderer
 
+log = logging.getLogger(__name__)
+
 
 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
     """
@@ -728,7 +731,7 @@
     return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
 
 
-def urlify_text(text):
+def urlify_text(text_):
     import re
 
     url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'''
@@ -738,8 +741,42 @@
         url_full = match_obj.groups()[0]
         return '<a href="%(url)s">%(url)s</a>' % ({'url':url_full})
 
-    return literal(url_pat.sub(url_func, text))
+    return literal(url_pat.sub(url_func, text_))
 
+def urlify_commit(text_):
+    import re
+    import traceback
+    
+    try:
+        conf = config['app_conf']
+        
+        URL_PAT = re.compile(r'%s' % conf.get('url_pat'))
+        
+        if URL_PAT:
+            ISSUE_SERVER = conf.get('issue_server')
+            ISSUE_PREFIX = conf.get('issue_prefix')
+            def url_func(match_obj):
+                issue_id = match_obj.groups()[0]
+                tmpl = (
+                '<a class="%(cls)s" href="%(url)s">'
+                ' %(issue-prefix)s%(id-repr)s'
+                '</a>'
+                )
+                return tmpl % (
+                    {
+                     'cls':'issue-tracker-link',
+                     'url':ISSUE_SERVER.replace('{id}',issue_id),
+                     'id-repr':issue_id,
+                     'issue-prefix':ISSUE_PREFIX,
+                     'serv':ISSUE_SERVER,
+                    }
+                )
+            return literal(URL_PAT.sub(url_func, text_))
+    except:
+        log.error(traceback.format_exc())
+        pass
+
+    return text_
 
 def rst(source):
     return literal('<div class="rst-block">%s</div>' %
--- a/rhodecode/lib/rcmail/exceptions.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/rcmail/exceptions.py	Sun Jan 08 12:18:16 2012 +0200
@@ -1,3 +1,4 @@
+
 
 class InvalidMessage(RuntimeError):
     """
@@ -5,6 +6,7 @@
     as recipients or sender address.
     """
 
+
 class BadHeaders(RuntimeError):
     """
     Raised if message contains newlines in headers.
--- a/rhodecode/lib/rcmail/message.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/rcmail/message.py	Sun Jan 08 12:18:16 2012 +0200
@@ -45,6 +45,8 @@
     :param bcc: BCC list
     :param extra_headers: dict of extra email headers
     :param attachments: list of Attachment instances
+    :param recipients_separator: alternative separator for any of
+        'From', 'To', 'Delivered-To', 'Cc', 'Bcc' fields
     """
 
     def __init__(self,
@@ -56,8 +58,8 @@
                  cc=None,
                  bcc=None,
                  extra_headers=None,
-                 attachments=None):
-
+                 attachments=None,
+                 recipients_separator="; "):
 
         self.subject = subject or ''
         self.sender = sender
@@ -70,6 +72,8 @@
         self.bcc = bcc or []
         self.extra_headers = extra_headers or {}
 
+        self.recipients_separator = recipients_separator
+
     @property
     def send_to(self):
         return set(self.recipients) | set(self.bcc or ()) | set(self.cc or ())
@@ -92,7 +96,8 @@
                                 To=self.recipients,
                                 From=self.sender,
                                 Body=self.body,
-                                Html=self.html)
+                                Html=self.html,
+                                separator=self.recipients_separator)
 
         if self.bcc:
             response.base['Bcc'] = self.bcc
--- a/rhodecode/lib/rcmail/response.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/rcmail/response.py	Sun Jan 08 12:18:16 2012 +0200
@@ -141,12 +141,14 @@
     MailResponse.to_message.  This lets you change it and work with it, then
     send it out when it's ready.
     """
-    def __init__(self, To=None, From=None, Subject=None, Body=None, Html=None):
+    def __init__(self, To=None, From=None, Subject=None, Body=None, Html=None, 
+                 separator="; "):
         self.Body = Body
         self.Html = Html
         self.base = MailBase([('To', To), ('From', From), ('Subject', Subject)])
         self.multipart = self.Body and self.Html
         self.attachments = []
+        self.separator = separator
 
     def __contains__(self, key):
         return self.base.__contains__(key)
@@ -298,7 +300,7 @@
             self.base.body = self.Html
             self.base.content_encoding['Content-Type'] = ('text/html', {})
 
-        return to_message(self.base)
+        return to_message(self.base, separator=self.separator)
 
     def all_parts(self):
         """
@@ -310,7 +312,7 @@
     def keys(self):
         return self.base.keys()
 
-def to_message(mail):
+def to_message(mail, separator="; "):
     """
     Given a MailBase message, this will construct a MIMEPart
     that is canonicalized for use with the Python email API.
@@ -339,10 +341,16 @@
 
     for k in mail.keys():
         if k in ADDRESS_HEADERS_WHITELIST:
-            out[k.encode('ascii')] = header_to_mime_encoding(mail[k])
+            out[k.encode('ascii')] = header_to_mime_encoding(
+                                         mail[k],
+                                         not_email=False,
+                                         separator=separator
+                                     )
         else:
-            out[k.encode('ascii')] = header_to_mime_encoding(mail[k],
-                                                             not_email=True)
+            out[k.encode('ascii')] = header_to_mime_encoding(
+                                         mail[k],
+                                         not_email=True
+                                    )
 
     out.extract_payload(mail)
 
@@ -403,12 +411,12 @@
             self.is_multipart())
 
 
-def header_to_mime_encoding(value, not_email=False):
+def header_to_mime_encoding(value, not_email=False, separator=", "):
     if not value: return ""
 
     encoder = Charset(DEFAULT_ENCODING)
     if type(value) == list:
-        return "; ".join(properly_encode_header(
+        return separator.join(properly_encode_header(
             v, encoder, not_email) for v in value)
     else:
         return properly_encode_header(value, encoder, not_email)
--- a/rhodecode/lib/rcmail/smtp_mailer.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/rcmail/smtp_mailer.py	Sun Jan 08 12:18:16 2012 +0200
@@ -59,7 +59,8 @@
 
         if isinstance(recipients, basestring):
             recipients = [recipients]
-        msg = Message(subject, recipients, body, html, self.mail_from)
+        msg = Message(subject, recipients, body, html, self.mail_from,
+                      recipients_separator=", ")
         raw_msg = msg.to_message()
 
         if self.ssl:
--- a/rhodecode/lib/utils.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/lib/utils.py	Sun Jan 08 12:18:16 2012 +0200
@@ -152,12 +152,12 @@
     """
     Scans given path for repos and return (name,(type,path)) tuple
 
-    :param path: path to scann for repositories
+    :param path: path to scan for repositories
     :param recursive: recursive search and return names with subdirs in front
     """
 
     # remove ending slash for better results
-    path = path.rstrip('/')
+    path = path.rstrip(os.sep)
 
     def _get_repos(p):
         if not os.access(p, os.W_OK):
--- a/rhodecode/model/notification.py	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/model/notification.py	Sun Jan 08 12:18:16 2012 +0200
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """
     rhodecode.model.notification
-    ~~~~~~~~~~~~~~
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
     Model for notifications
 
--- a/rhodecode/templates/changelog/changelog.html	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/templates/changelog/changelog.html	Sun Jan 08 12:18:16 2012 +0200
@@ -48,7 +48,7 @@
 						<div class="left">
 							<div>
 							${h.checkbox(cs.short_id,class_="changeset_range")}
-							<span class="changeset_id">${cs.revision}:<span class="changeset_hash">${h.short_id(cs.raw_id)}</span></span>
+							<span class="tooltip" title="${cs.date}"><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}"><span class="changeset_id">${cs.revision}:<span class="changeset_hash">${h.short_id(cs.raw_id)}</span></span></a></span>
 							</div>
 							<div class="author">
 								<div class="gravatar">
--- a/rhodecode/templates/changeset/changeset.html	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/templates/changeset/changeset.html	Sun Jan 08 12:18:16 2012 +0200
@@ -49,7 +49,7 @@
 	                     <span>${h.person(c.changeset.author)}</span><br/>
 	                     <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
 	                 </div>
-	                 <div class="message">${h.wrap_paragraphs(c.changeset.message)}</div>
+	                 <div class="message">${h.urlify_commit(h.wrap_paragraphs(c.changeset.message))}</div>
 	             </div>
 	             <div class="right">
 		             <div class="changes">
@@ -95,7 +95,7 @@
 	                    <div class="cs_${change}">
                             <div class="node">
                             %if change != 'removed':
-                                ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path))}
+                                ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path)+"_target")}
                             %else:
                                 ${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
                             %endif
@@ -138,11 +138,15 @@
           YUE.on(YUQ('.show-inline-comments'),'change',function(e){
               var show = 'none';
               var target = e.currentTarget;
+              console.log(target);
               if(target.checked){
                   var show = ''
               }
+              console.log('aa')
               var boxid = YUD.getAttribute(target,'id_for');
+              console.log(boxid);
               var comments = YUQ('#{0} .inline-comments'.format(boxid));
+              console.log(comments)
               for(c in comments){ 
                  YUD.setStyle(comments[c],'display',show);
               }
--- a/rhodecode/templates/changeset/changeset_range.html	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/templates/changeset/changeset_range.html	Sun Jan 08 12:18:16 2012 +0200
@@ -41,7 +41,7 @@
                 <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td>
                 <td><div class="author">${h.person(cs.author)}</div></td>
                 <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
-                <td><div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div></td>
+                <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message))}</div></td>
                 </tr>
             %endfor
             </table>
--- a/rhodecode/templates/changeset/diff_block.html	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/templates/changeset/diff_block.html	Sun Jan 08 12:18:16 2012 +0200
@@ -7,8 +7,8 @@
 
 %for change,filenode,diff,cs1,cs2,stat in changes:
     %if change !='removed':
-    <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" style="clear:both;height:90px;margin-top:-60px"></div>
-    <div class="diffblock  margined comm">
+    <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}_target" style="clear:both;height:90px;margin-top:-60px"></div>
+    <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" class="diffblock  margined comm">
         <div class="code-header">
             <div class="changeset_header">
                 <div class="changeset_file">
--- a/rhodecode/templates/shortlog/shortlog_data.html	Sat Jan 07 21:44:18 2012 +0200
+++ b/rhodecode/templates/shortlog/shortlog_data.html	Sun Jan 08 12:18:16 2012 +0200
@@ -2,16 +2,19 @@
 %if c.repo_changesets:
 <table class="table_disp">
 	<tr>
-		<th class="left">${_('commit message')}</th>
+	    <th class="left">${_('revision')}</th>	
+        <th class="left">${_('commit message')}</th>
 		<th class="left">${_('age')}</th>
 		<th class="left">${_('author')}</th>
-		<th class="left">${_('revision')}</th>
 		<th class="left">${_('branch')}</th>
 		<th class="left">${_('tags')}</th>
 	</tr>
 %for cnt,cs in enumerate(c.repo_changesets):
 	<tr class="parity${cnt%2}">
         <td>
+            <div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div>
+        </td>  
+        <td>
             ${h.link_to(h.truncate(cs.message,50),
             h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
             title=cs.message)}
@@ -20,7 +23,6 @@
                       ${h.age(cs.date)}</span>
         </td>        	
 		<td title="${cs.author}">${h.person(cs.author)}</td>
-		<td><div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div></td>
 		<td>
 			<span class="logtags">
 				<span class="branchtag">${cs.branch}</span>