##// END OF EJS Templates
git-lfs: enable support for detection of git-lfs requests type...
marcink -
r1565:8dba6b09 default
parent child Browse files
Show More
@@ -1,85 +1,153 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 SimpleGit middleware for handling git protocol request (push/clone etc.)
23 23 It's implemented with basic auth function
24 24 """
25 import os
25 26 import re
26 27 import logging
27 28 import urlparse
28 29
29 30 import rhodecode
30 31 from rhodecode.lib import utils2
31 32 from rhodecode.lib.middleware import simplevcs
32 33
33 34 log = logging.getLogger(__name__)
34 35
35 36
36 37 GIT_PROTO_PAT = re.compile(
37 r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
38 r'^/(.+)/(info/refs|info/lfs/(.+)|git-upload-pack|git-receive-pack)')
39 GIT_LFS_PROTO_PAT = re.compile(r'^/(.+)/(info/lfs/(.+))')
40
41
42 def default_lfs_store():
43 """
44 Default lfs store location, it's consistent with Mercurials large file
45 store which is in .cache/largefiles
46 """
47 from rhodecode.lib.vcs.backends.git import lfs_store
48 user_home = os.path.expanduser("~")
49 return lfs_store(user_home)
38 50
39 51
40 52 class SimpleGit(simplevcs.SimpleVCS):
41 53
42 54 SCM = 'git'
43 55
44 56 def _get_repository_name(self, environ):
45 57 """
46 58 Gets repository name out of PATH_INFO header
47 59
48 60 :param environ: environ where PATH_INFO is stored
49 61 """
50 62 repo_name = GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
63 # for GIT LFS, and bare format strip .git suffix from names
64 if repo_name.endswith('.git'):
65 repo_name = repo_name[:-4]
51 66 return repo_name
52 67
68 def _get_lfs_action(self, path, request_method):
69 """
70 return an action based on LFS requests type.
71 Those routes are handled inside vcsserver app.
72
73 batch -> POST to /info/lfs/objects/batch => PUSH/PULL
74 batch is based on the `operation.
75 that could be download or upload, but those are only
76 instructions to fetch so we return pull always
77
78 download -> GET to /info/lfs/{oid} => PULL
79 upload -> PUT to /info/lfs/{oid} => PUSH
80
81 verification -> POST to /info/lfs/verify => PULL
82
83 """
84
85 match_obj = GIT_LFS_PROTO_PAT.match(path)
86 _parts = match_obj.groups()
87 repo_name, path, operation = _parts
88 log.debug(
89 'LFS: detecting operation based on following '
90 'data: %s, req_method:%s', _parts, request_method)
91
92 if operation == 'verify':
93 return 'pull'
94 elif operation == 'objects/batch':
95 # batch sends back instructions for API to dl/upl we report it
96 # as pull
97 if request_method == 'POST':
98 return 'pull'
99
100 elif operation:
101 # probably a OID, upload is PUT, download a GET
102 if request_method == 'GET':
103 return 'pull'
104 else:
105 return 'push'
106
107 # if default not found require push, as action
108 return 'push'
109
53 110 _ACTION_MAPPING = {
54 111 'git-receive-pack': 'push',
55 112 'git-upload-pack': 'pull',
56 113 }
57 114
58 115 def _get_action(self, environ):
59 116 """
60 117 Maps git request commands into a pull or push command.
61 118 In case of unknown/unexpected data, it returns 'pull' to be safe.
62 119
63 120 :param environ:
64 121 """
65 122 path = environ['PATH_INFO']
66 123
67 124 if path.endswith('/info/refs'):
68 125 query = urlparse.parse_qs(environ['QUERY_STRING'])
69 126 service_cmd = query.get('service', [''])[0]
70 127 return self._ACTION_MAPPING.get(service_cmd, 'pull')
128
129 elif GIT_LFS_PROTO_PAT.match(environ['PATH_INFO']):
130 return self._get_lfs_action(
131 environ['PATH_INFO'], environ['REQUEST_METHOD'])
132
71 133 elif path.endswith('/git-receive-pack'):
72 134 return 'push'
73 135 elif path.endswith('/git-upload-pack'):
74 136 return 'pull'
75 137
76 138 return 'pull'
77 139
78 140 def _create_wsgi_app(self, repo_path, repo_name, config):
79 141 return self.scm_app.create_git_wsgi_app(
80 142 repo_path, repo_name, config)
81 143
82 144 def _create_config(self, extras, repo_name):
83 145 extras['git_update_server_info'] = utils2.str2bool(
84 146 rhodecode.CONFIG.get('git_update_server_info'))
147
148 # TODO(marcink): controll this via DB settings, store and enabled-per
149 # repo settings
150
151 extras['git_lfs_enabled'] = True
152 extras['git_lfs_store_path'] = default_lfs_store()
85 153 return extras
General Comments 0
You need to be logged in to leave comments. Login now