Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: gclient_scm.py

Issue 235005: gclient_scm: add support for .git (Closed)
Patch Set: Fixed per code review. Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « PRESUBMIT.py ('k') | tests/gclient_scm_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2009 Google Inc. All Rights Reserved. 1 # Copyright 2009 Google Inc. All Rights Reserved.
2 # 2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); 3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License. 4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at 5 # You may obtain a copy of the License at
6 # 6 #
7 # http://www.apache.org/licenses/LICENSE-2.0 7 # http://www.apache.org/licenses/LICENSE-2.0
8 # 8 #
9 # Unless required by applicable law or agreed to in writing, software 9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, 10 # distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 16 matching lines...) Expand all
27 27
28 ### SCM abstraction layer 28 ### SCM abstraction layer
29 29
30 30
31 # Factory Method for SCM wrapper creation 31 # Factory Method for SCM wrapper creation
32 32
33 def CreateSCM(url=None, root_dir=None, relpath=None, scm_name='svn'): 33 def CreateSCM(url=None, root_dir=None, relpath=None, scm_name='svn'):
34 # TODO(maruel): Deduce the SCM from the url. 34 # TODO(maruel): Deduce the SCM from the url.
35 scm_map = { 35 scm_map = {
36 'svn' : SVNWrapper, 36 'svn' : SVNWrapper,
37 'git' : GitWrapper,
37 } 38 }
39
40 if url and (url.startswith('git:') or
41 url.startswith('ssh:') or
42 url.endswith('.git')):
43 scm_name = 'git'
44
38 if not scm_name in scm_map: 45 if not scm_name in scm_map:
39 raise gclient_utils.Error('Unsupported scm %s' % scm_name) 46 raise gclient_utils.Error('Unsupported scm %s' % scm_name)
40 return scm_map[scm_name](url, root_dir, relpath, scm_name) 47 return scm_map[scm_name](url, root_dir, relpath, scm_name)
41 48
42 49
43 # SCMWrapper base class 50 # SCMWrapper base class
44 51
45 class SCMWrapper(object): 52 class SCMWrapper(object):
46 """Add necessary glue between all the supported SCM. 53 """Add necessary glue between all the supported SCM.
47 54
48 This is the abstraction layer to bind to different SCM. Since currently only 55 This is the abstraction layer to bind to different SCM. Since currently only
49 subversion is supported, a lot of subersionism remains. This can be sorted out 56 subversion is supported, a lot of subersionism remains. This can be sorted out
50 once another SCM is supported.""" 57 once another SCM is supported."""
51 def __init__(self, url=None, root_dir=None, relpath=None, 58 def __init__(self, url=None, root_dir=None, relpath=None,
52 scm_name='svn'): 59 scm_name='svn'):
53 self.scm_name = scm_name 60 self.scm_name = scm_name
54 self.url = url 61 self.url = url
55 self._root_dir = root_dir 62 self._root_dir = root_dir
56 if self._root_dir: 63 if self._root_dir:
57 self._root_dir = self._root_dir.replace('/', os.sep) 64 self._root_dir = self._root_dir.replace('/', os.sep)
58 self.relpath = relpath 65 self.relpath = relpath
59 if self.relpath: 66 if self.relpath:
60 self.relpath = self.relpath.replace('/', os.sep) 67 self.relpath = self.relpath.replace('/', os.sep)
68 if self.relpath and self._root_dir:
69 self.checkout_path = os.path.join(self._root_dir, self.relpath)
61 70
62 def FullUrlForRelativeUrl(self, url): 71 def FullUrlForRelativeUrl(self, url):
63 # Find the forth '/' and strip from there. A bit hackish. 72 # Find the forth '/' and strip from there. A bit hackish.
64 return '/'.join(self.url.split('/')[:4]) + url 73 return '/'.join(self.url.split('/')[:4]) + url
65 74
66 def RunCommand(self, command, options, args, file_list=None): 75 def RunCommand(self, command, options, args, file_list=None):
67 # file_list will have all files that are modified appended to it. 76 # file_list will have all files that are modified appended to it.
68 if file_list is None: 77 if file_list is None:
69 file_list = [] 78 file_list = []
70 79
71 commands = ['cleanup', 'export', 'update', 'revert', 80 commands = ['cleanup', 'export', 'update', 'revert',
72 'status', 'diff', 'pack', 'runhooks'] 81 'status', 'diff', 'pack', 'runhooks']
73 82
74 if not command in commands: 83 if not command in commands:
75 raise gclient_utils.Error('Unknown command %s' % command) 84 raise gclient_utils.Error('Unknown command %s' % command)
76 85
77 if not command in dir(self): 86 if not command in dir(self):
78 raise gclient_utils.Error('Command %s not implemnted in %s wrapper' % ( 87 raise gclient_utils.Error('Command %s not implemnted in %s wrapper' % (
79 command, self.scm_name)) 88 command, self.scm_name))
80 89
81 return getattr(self, command)(options, args, file_list) 90 return getattr(self, command)(options, args, file_list)
82 91
83 92
93 class GitWrapper(SCMWrapper):
94 """Wrapper for Git"""
95
96 def cleanup(self, options, args, file_list):
97 """Cleanup working copy."""
98 self._RunGit(['prune'])
99 self._RunGit(['fsck'])
100 self._RunGit(['gc'])
101
102 def diff(self, options, args, file_list):
103 # NOTE: This function does not currently modify file_list.
104 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin'])
105 print self._RunGit(['diff', merge_base])
106
107 def export(self, options, args, file_list):
108 assert len(args) == 1
109 export_path = os.path.abspath(os.path.join(args[0], self.relpath))
110 if not os.path.exists(export_path):
111 os.makedirs(export_path)
112 self._RunGit(['checkout-index', '-a', '--prefix=%s/' % export_path])
113
114 def update(self, options, args, file_list):
115 """Runs git to update or transparently checkout the working copy.
116
117 All updated files will be appended to file_list.
118
119 Raises:
120 Error: if can't get URL for relative path.
121 """
122
123 if args:
124 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args))
125
126 components = self.url.split("@")
127 url = components[0]
128 revision = None
129 if options.revision:
130 revision = options.revision
131 elif len(components) == 2:
132 revision = components[1]
133
134 if not os.path.exists(self.checkout_path):
135 self._RunGit(['clone', '-q', url, self.checkout_path], cwd=self._root_dir)
136 if revision:
137 self._RunGit(['reset', '--hard', revision])
138 files = self._RunGit(['ls-files']).split()
139 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
140 return
141
142 self._RunGit(['remote', 'update'])
143 new_base = 'origin'
144 if revision:
145 new_base = revision
146 files = self._RunGit(['diff', new_base, '--name-only']).split()
147 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
148 self._RunGit(['rebase', new_base])
149
150 def revert(self, options, args, file_list):
151 """Reverts local modifications.
152
153 All reverted files will be appended to file_list.
154 """
155 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin'])
156 files = self._RunGit(['diff', merge_base, '--name-only']).split()
157 print self._RunGit(['reset', '--hard', merge_base])
158 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
159
160 def runhooks(self, options, args, file_list):
161 self.status(options, args, file_list)
162
163 def status(self, options, args, file_list):
164 """Display status information."""
165 if not os.path.isdir(self.checkout_path):
166 print('\n________ couldn\'t run status in %s:\nThe directory '
167 'does not exist.' % checkout_path)
168 else:
169 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin'])
170 print self._RunGit(['diff', '--name-status', merge_base])
171 files = self._RunGit(['diff', '--name-only', merge_base]).split()
172 file_list.extend([os.path.join(self.checkout_path, f) for f in files])
173
174 def _RunGit(self, args, cwd=None, checkrc=True):
175 if cwd == None:
176 cwd = self.checkout_path
177 cmd = ['git']
178 cmd.extend(args)
179 sp = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE)
180 if checkrc and sp.returncode:
181 raise gclient_utils.Error('git command %s returned %d' %
182 (args[0], sp.returncode))
183 return sp.communicate()[0].strip()
184
185
84 class SVNWrapper(SCMWrapper): 186 class SVNWrapper(SCMWrapper):
85 """ Wrapper for SVN """ 187 """ Wrapper for SVN """
86 188
87 def cleanup(self, options, args, file_list): 189 def cleanup(self, options, args, file_list):
88 """Cleanup working copy.""" 190 """Cleanup working copy."""
89 command = ['cleanup'] 191 command = ['cleanup']
90 command.extend(args) 192 command.extend(args)
91 RunSVN(command, os.path.join(self._root_dir, self.relpath)) 193 RunSVN(command, os.path.join(self._root_dir, self.relpath))
92 194
93 def diff(self, options, args, file_list): 195 def diff(self, options, args, file_list):
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 # Col 3 691 # Col 3
590 if wc_status[0].getAttribute('copied') == 'true': 692 if wc_status[0].getAttribute('copied') == 'true':
591 statuses[3] = '+' 693 statuses[3] = '+'
592 # Col 4 694 # Col 4
593 if wc_status[0].getAttribute('switched') == 'true': 695 if wc_status[0].getAttribute('switched') == 'true':
594 statuses[4] = 'S' 696 statuses[4] = 'S'
595 # TODO(maruel): Col 5 and 6 697 # TODO(maruel): Col 5 and 6
596 item = (''.join(statuses), file) 698 item = (''.join(statuses), file)
597 results.append(item) 699 results.append(item)
598 return results 700 return results
OLDNEW
« no previous file with comments | « PRESUBMIT.py ('k') | tests/gclient_scm_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698