OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Meta checkout manager supporting both Subversion and GIT.""" | 6 """Meta checkout manager supporting both Subversion and GIT.""" |
7 # Files | 7 # Files |
8 # .gclient : Current client configuration, written by 'config' command. | 8 # .gclient : Current client configuration, written by 'config' command. |
9 # Format is a Python script defining 'solutions', a list whose | 9 # Format is a Python script defining 'solutions', a list whose |
10 # entries each are maps binding the strings "name" and "url" | 10 # entries each are maps binding the strings "name" and "url" |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 | 166 |
167 sub_target_name is an optional parameter if the module name in the other | 167 sub_target_name is an optional parameter if the module name in the other |
168 DEPS file is different. E.g., you might want to map src/net to net.""" | 168 DEPS file is different. E.g., you might want to map src/net to net.""" |
169 self.module_name = module_name | 169 self.module_name = module_name |
170 self.sub_target_name = sub_target_name | 170 self.sub_target_name = sub_target_name |
171 | 171 |
172 def __str__(self): | 172 def __str__(self): |
173 return 'From(%s, %s)' % (repr(self.module_name), | 173 return 'From(%s, %s)' % (repr(self.module_name), |
174 repr(self.sub_target_name)) | 174 repr(self.sub_target_name)) |
175 | 175 |
176 class FileImpl(object): | |
177 """Used to implement the File('') syntax which lets you sync a single file | |
178 from a SVN repo.""" | |
179 | |
180 def __init__(self, file_location): | |
181 self.file_location = file_location | |
182 | |
183 def __str__(self): | |
184 return 'File("%s")' % self.file_location | |
185 | |
186 def GetPath(self): | |
187 return os.path.split(self.file_location)[0] | |
188 | |
189 def GetFilename(self): | |
190 rev_tokens = self.file_location.split('@') | |
191 return os.path.split(rev_tokens[0])[1] | |
192 | |
193 def GetRevision(self): | |
194 rev_tokens = self.file_location.split('@') | |
195 if len(rev_tokens) > 1: | |
196 return rev_tokens[1] | |
197 return None | |
198 | |
199 class VarImpl(object): | 176 class VarImpl(object): |
200 def __init__(self, custom_vars, local_scope): | 177 def __init__(self, custom_vars, local_scope): |
201 self._custom_vars = custom_vars | 178 self._custom_vars = custom_vars |
202 self._local_scope = local_scope | 179 self._local_scope = local_scope |
203 | 180 |
204 def Lookup(self, var_name): | 181 def Lookup(self, var_name): |
205 """Implements the Var syntax.""" | 182 """Implements the Var syntax.""" |
206 if var_name in self._custom_vars: | 183 if var_name in self._custom_vars: |
207 return self._custom_vars[var_name] | 184 return self._custom_vars[var_name] |
208 elif var_name in self._local_scope.get("vars", {}): | 185 elif var_name in self._local_scope.get("vars", {}): |
(...skipping 28 matching lines...) Expand all Loading... | |
237 self._relative = relative | 214 self._relative = relative |
238 # This is a mutable value which has the list of 'target_os' OSes listed in | 215 # This is a mutable value which has the list of 'target_os' OSes listed in |
239 # the current deps file. | 216 # the current deps file. |
240 self.local_target_os = None | 217 self.local_target_os = None |
241 | 218 |
242 # These are only set in .gclient and not in DEPS files. | 219 # These are only set in .gclient and not in DEPS files. |
243 self._custom_vars = custom_vars or {} | 220 self._custom_vars = custom_vars or {} |
244 self._custom_deps = custom_deps or {} | 221 self._custom_deps = custom_deps or {} |
245 self._custom_hooks = custom_hooks or [] | 222 self._custom_hooks = custom_hooks or [] |
246 | 223 |
247 # TODO(iannucci): Remove this when all masters are correctly substituting | |
248 # the new blink url. | |
249 if (self._custom_vars.get('webkit_trunk', '') == | |
250 'svn://svn-mirror.golo.chromium.org/webkit-readonly/trunk'): | |
251 new_url = 'svn://svn-mirror.golo.chromium.org/blink/trunk' | |
252 print('Overwriting Var("webkit_trunk") with %s' % new_url) | |
253 self._custom_vars['webkit_trunk'] = new_url | |
254 | |
255 # Post process the url to remove trailing slashes. | 224 # Post process the url to remove trailing slashes. |
256 if isinstance(self._url, basestring): | 225 if isinstance(self._url, basestring): |
257 # urls are sometime incorrectly written as proto://host/path/@rev. Replace | 226 # urls are sometime incorrectly written as proto://host/path/@rev. Replace |
258 # it to proto://host/path@rev. | 227 # it to proto://host/path@rev. |
259 self._url = self._url.replace('/@', '@') | 228 self._url = self._url.replace('/@', '@') |
260 elif not isinstance(self._url, | 229 elif not isinstance(self._url, (self.FromImpl, None.__class__)): |
261 (self.FromImpl, self.FileImpl, None.__class__)): | |
262 raise gclient_utils.Error( | 230 raise gclient_utils.Error( |
263 ('dependency url must be either a string, None, ' | 231 ('dependency url must be either a string, None, ' |
264 'File() or From() instead of %s') % self._url.__class__.__name__) | 232 'or From() instead of %s') % self._url.__class__.__name__) |
265 # Make any deps_file path platform-appropriate. | 233 # Make any deps_file path platform-appropriate. |
266 for sep in ['/', '\\']: | 234 for sep in ['/', '\\']: |
267 self._deps_file = self._deps_file.replace(sep, os.sep) | 235 self._deps_file = self._deps_file.replace(sep, os.sep) |
268 | 236 |
269 @property | 237 @property |
270 def deps_file(self): | 238 def deps_file(self): |
271 return self._deps_file | 239 return self._deps_file |
272 | 240 |
273 @property | 241 @property |
274 def managed(self): | 242 def managed(self): |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
527 parsed_url = urlparse.urlparse(url) | 495 parsed_url = urlparse.urlparse(url) |
528 if (not parsed_url[0] and | 496 if (not parsed_url[0] and |
529 not re.match(r'^\w+\@[\w\.-]+\:[\w\/]+', parsed_url[2])): | 497 not re.match(r'^\w+\@[\w\.-]+\:[\w\/]+', parsed_url[2])): |
530 # A relative url. Fetch the real base. | 498 # A relative url. Fetch the real base. |
531 path = parsed_url[2] | 499 path = parsed_url[2] |
532 if not path.startswith('/'): | 500 if not path.startswith('/'): |
533 raise gclient_utils.Error( | 501 raise gclient_utils.Error( |
534 'relative DEPS entry \'%s\' must begin with a slash' % url) | 502 'relative DEPS entry \'%s\' must begin with a slash' % url) |
535 # Create a scm just to query the full url. | 503 # Create a scm just to query the full url. |
536 parent_url = self.parent.parsed_url | 504 parent_url = self.parent.parsed_url |
537 if isinstance(parent_url, self.FileImpl): | |
538 parent_url = parent_url.file_location | |
539 scm = gclient_scm.CreateSCM( | 505 scm = gclient_scm.CreateSCM( |
540 parent_url, self.root.root_dir, None, self.outbuf) | 506 parent_url, self.root.root_dir, None, self.outbuf) |
541 parsed_url = scm.FullUrlForRelativeUrl(url) | 507 parsed_url = scm.FullUrlForRelativeUrl(url) |
542 else: | 508 else: |
543 parsed_url = url | 509 parsed_url = url |
544 logging.info( | 510 logging.info( |
545 'Dependency(%s).LateOverride(%s) -> %s' % | 511 'Dependency(%s).LateOverride(%s) -> %s' % |
546 (self.name, url, parsed_url)) | 512 (self.name, url, parsed_url)) |
547 return parsed_url | 513 return parsed_url |
548 | 514 |
549 if isinstance(url, self.FileImpl): | |
550 logging.info( | |
551 'Dependency(%s).LateOverride(%s) -> %s (File)' % | |
552 (self.name, url, url)) | |
553 return url | |
554 | |
555 if url is None: | 515 if url is None: |
556 logging.info( | 516 logging.info( |
557 'Dependency(%s).LateOverride(%s) -> %s' % (self.name, url, url)) | 517 'Dependency(%s).LateOverride(%s) -> %s' % (self.name, url, url)) |
558 return url | 518 return url |
559 | 519 |
560 raise gclient_utils.Error('Unknown url type') | 520 raise gclient_utils.Error('Unknown url type') |
561 | 521 |
562 @staticmethod | 522 @staticmethod |
563 def MergeWithOsDeps(deps, deps_os, target_os_list): | 523 def MergeWithOsDeps(deps, deps_os, target_os_list): |
564 """Returns a new "deps" structure that is the deps sent in updated | 524 """Returns a new "deps" structure that is the deps sent in updated |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
635 if use_strict: | 595 if use_strict: |
636 logging.info( | 596 logging.info( |
637 'ParseDepsFile(%s): Strict Mode Enabled', self.name) | 597 'ParseDepsFile(%s): Strict Mode Enabled', self.name) |
638 global_scope = { | 598 global_scope = { |
639 '__builtins__': {'None': None}, | 599 '__builtins__': {'None': None}, |
640 'Var': var.Lookup, | 600 'Var': var.Lookup, |
641 'deps_os': {}, | 601 'deps_os': {}, |
642 } | 602 } |
643 else: | 603 else: |
644 global_scope = { | 604 global_scope = { |
645 'File': self.FileImpl, | |
646 'From': self.FromImpl, | 605 'From': self.FromImpl, |
647 'Var': var.Lookup, | 606 'Var': var.Lookup, |
648 'deps_os': {}, | 607 'deps_os': {}, |
649 } | 608 } |
650 # Eval the content. | 609 # Eval the content. |
651 try: | 610 try: |
652 exec(deps_content, global_scope, local_scope) | 611 exec(deps_content, global_scope, local_scope) |
653 except SyntaxError as e: | 612 except SyntaxError as e: |
654 gclient_utils.SyntaxErrorToError(filepath, e) | 613 gclient_utils.SyntaxErrorToError(filepath, e) |
655 if use_strict: | 614 if use_strict: |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
835 if not self.should_process: | 794 if not self.should_process: |
836 return | 795 return |
837 # When running runhooks, there's no need to consult the SCM. | 796 # When running runhooks, there's no need to consult the SCM. |
838 # All known hooks are expected to run unconditionally regardless of working | 797 # All known hooks are expected to run unconditionally regardless of working |
839 # copy state, so skip the SCM status check. | 798 # copy state, so skip the SCM status check. |
840 run_scm = command not in ('runhooks', 'recurse', None) | 799 run_scm = command not in ('runhooks', 'recurse', None) |
841 parsed_url = self.LateOverride(self.url) | 800 parsed_url = self.LateOverride(self.url) |
842 file_list = [] if not options.nohooks else None | 801 file_list = [] if not options.nohooks else None |
843 revision_override = revision_overrides.pop(self.name, None) | 802 revision_override = revision_overrides.pop(self.name, None) |
844 if run_scm and parsed_url: | 803 if run_scm and parsed_url: |
845 if isinstance(parsed_url, self.FileImpl): | 804 # Create a shallow copy to mutate revision. |
846 # Special support for single-file checkout. | 805 options = copy.copy(options) |
847 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): | 806 options.revision = revision_override |
848 # Sadly, pylint doesn't realize that parsed_url is of FileImpl. | 807 self.maybeGetParentRevision( |
849 # pylint: disable=E1103 | 808 command, options, parsed_url, self.parent) |
850 options.revision = parsed_url.GetRevision() | 809 self._used_revision = options.revision |
851 self._used_scm = gclient_scm.SVNWrapper( | 810 self._used_scm = gclient_scm.CreateSCM( |
852 parsed_url.GetPath(), self.root.root_dir, self.name, | 811 parsed_url, self.root.root_dir, self.name, self.outbuf, |
853 out_cb=work_queue.out_cb) | 812 out_cb=work_queue.out_cb) |
854 self._used_scm.RunCommand('updatesingle', | 813 self._got_revision = self._used_scm.RunCommand(command, options, args, |
855 options, args + [parsed_url.GetFilename()], file_list) | 814 file_list) |
856 else: | 815 if file_list: |
857 # Create a shallow copy to mutate revision. | 816 file_list = [os.path.join(self.name, f.strip()) for f in file_list] |
858 options = copy.copy(options) | |
859 options.revision = revision_override | |
860 self.maybeGetParentRevision( | |
861 command, options, parsed_url, self.parent) | |
862 self._used_revision = options.revision | |
863 self._used_scm = gclient_scm.CreateSCM( | |
864 parsed_url, self.root.root_dir, self.name, self.outbuf, | |
865 out_cb=work_queue.out_cb) | |
866 self._got_revision = self._used_scm.RunCommand(command, options, args, | |
867 file_list) | |
868 if file_list: | |
869 file_list = [os.path.join(self.name, f.strip()) for f in file_list] | |
870 | 817 |
871 # TODO(phajdan.jr): We should know exactly when the paths are absolute. | 818 # TODO(phajdan.jr): We should know exactly when the paths are absolute. |
872 # Convert all absolute paths to relative. | 819 # Convert all absolute paths to relative. |
873 for i in range(len(file_list or [])): | 820 for i in range(len(file_list or [])): |
874 # It depends on the command being executed (like runhooks vs sync). | 821 # It depends on the command being executed (like runhooks vs sync). |
875 if not os.path.isabs(file_list[i]): | 822 if not os.path.isabs(file_list[i]): |
876 continue | 823 continue |
877 prefix = os.path.commonprefix( | 824 prefix = os.path.commonprefix( |
878 [self.root.root_dir.lower(), file_list[i].lower()]) | 825 [self.root.root_dir.lower(), file_list[i].lower()]) |
879 file_list[i] = file_list[i][len(prefix):] | 826 file_list[i] = file_list[i][len(prefix):] |
880 # Strip any leading path separators. | 827 # Strip any leading path separators. |
881 while file_list[i].startswith(('\\', '/')): | 828 while file_list[i].startswith(('\\', '/')): |
882 file_list[i] = file_list[i][1:] | 829 file_list[i] = file_list[i][1:] |
883 | 830 |
884 # Always parse the DEPS file. | 831 # Always parse the DEPS file. |
885 self.ParseDepsFile() | 832 self.ParseDepsFile() |
886 self._run_is_done(file_list or [], parsed_url) | 833 self._run_is_done(file_list or [], parsed_url) |
887 if command in ('update', 'revert') and not options.noprehooks: | 834 if command in ('update', 'revert') and not options.noprehooks: |
888 self.RunPreDepsHooks() | 835 self.RunPreDepsHooks() |
889 | 836 |
890 if self.recursion_limit: | 837 if self.recursion_limit: |
891 # Parse the dependencies of this dependency. | 838 # Parse the dependencies of this dependency. |
892 for s in self.dependencies: | 839 for s in self.dependencies: |
893 work_queue.enqueue(s) | 840 work_queue.enqueue(s) |
894 | 841 |
895 if command == 'recurse': | 842 if command == 'recurse': |
896 if not isinstance(parsed_url, self.FileImpl): | 843 # Skip file only checkout. |
897 # Skip file only checkout. | 844 scm = gclient_scm.GetScmName(parsed_url) |
898 scm = gclient_scm.GetScmName(parsed_url) | 845 if not options.scm or scm in options.scm: |
899 if not options.scm or scm in options.scm: | 846 cwd = os.path.normpath(os.path.join(self.root.root_dir, self.name)) |
900 cwd = os.path.normpath(os.path.join(self.root.root_dir, self.name)) | 847 # Pass in the SCM type as an env variable. Make sure we don't put |
901 # Pass in the SCM type as an env variable. Make sure we don't put | 848 # unicode strings in the environment. |
902 # unicode strings in the environment. | 849 env = os.environ.copy() |
903 env = os.environ.copy() | 850 if scm: |
904 if scm: | 851 env['GCLIENT_SCM'] = str(scm) |
905 env['GCLIENT_SCM'] = str(scm) | 852 if parsed_url: |
906 if parsed_url: | 853 env['GCLIENT_URL'] = str(parsed_url) |
907 env['GCLIENT_URL'] = str(parsed_url) | 854 env['GCLIENT_DEP_PATH'] = str(self.name) |
908 env['GCLIENT_DEP_PATH'] = str(self.name) | 855 if options.prepend_dir and scm == 'git': |
909 if options.prepend_dir and scm == 'git': | 856 print_stdout = False |
910 print_stdout = False | 857 def filter_fn(line): |
911 def filter_fn(line): | 858 """Git-specific path marshaling. It is optimized for git-grep.""" |
912 """Git-specific path marshaling. It is optimized for git-grep.""" | |
913 | 859 |
914 def mod_path(git_pathspec): | 860 def mod_path(git_pathspec): |
915 match = re.match('^(\\S+?:)?([^\0]+)$', git_pathspec) | 861 match = re.match('^(\\S+?:)?([^\0]+)$', git_pathspec) |
916 modified_path = os.path.join(self.name, match.group(2)) | 862 modified_path = os.path.join(self.name, match.group(2)) |
917 branch = match.group(1) or '' | 863 branch = match.group(1) or '' |
918 return '%s%s' % (branch, modified_path) | 864 return '%s%s' % (branch, modified_path) |
919 | 865 |
920 match = re.match('^Binary file ([^\0]+) matches$', line) | 866 match = re.match('^Binary file ([^\0]+) matches$', line) |
921 if match: | 867 if match: |
922 print('Binary file %s matches\n' % mod_path(match.group(1))) | 868 print('Binary file %s matches\n' % mod_path(match.group(1))) |
923 return | 869 return |
924 | 870 |
925 items = line.split('\0') | 871 items = line.split('\0') |
926 if len(items) == 2 and items[1]: | 872 if len(items) == 2 and items[1]: |
927 print('%s : %s' % (mod_path(items[0]), items[1])) | 873 print('%s : %s' % (mod_path(items[0]), items[1])) |
928 elif len(items) >= 2: | 874 elif len(items) >= 2: |
929 # Multiple null bytes or a single trailing null byte indicate | 875 # Multiple null bytes or a single trailing null byte indicate |
930 # git is likely displaying filenames only (such as with -l) | 876 # git is likely displaying filenames only (such as with -l) |
931 print('\n'.join(mod_path(path) for path in items if path)) | 877 print('\n'.join(mod_path(path) for path in items if path)) |
932 else: | 878 else: |
933 print(line) | 879 print(line) |
934 else: | 880 else: |
935 print_stdout = True | 881 print_stdout = True |
936 filter_fn = None | 882 filter_fn = None |
937 | 883 |
938 if parsed_url is None: | 884 if parsed_url is None: |
939 print('Skipped omitted dependency %s' % cwd, file=sys.stderr) | 885 print('Skipped omitted dependency %s' % cwd, file=sys.stderr) |
940 elif os.path.isdir(cwd): | 886 elif os.path.isdir(cwd): |
941 try: | 887 try: |
942 gclient_utils.CheckCallAndFilter( | 888 gclient_utils.CheckCallAndFilter( |
943 args, cwd=cwd, env=env, print_stdout=print_stdout, | 889 args, cwd=cwd, env=env, print_stdout=print_stdout, |
944 filter_fn=filter_fn, | 890 filter_fn=filter_fn, |
945 ) | 891 ) |
946 except subprocess2.CalledProcessError: | 892 except subprocess2.CalledProcessError: |
947 if not options.ignore: | 893 if not options.ignore: |
948 raise | 894 raise |
949 else: | 895 else: |
950 print('Skipped missing %s' % cwd, file=sys.stderr) | 896 print('Skipped missing %s' % cwd, file=sys.stderr) |
951 | 897 |
952 | 898 |
953 @gclient_utils.lockedmethod | 899 @gclient_utils.lockedmethod |
954 def _run_is_done(self, file_list, parsed_url): | 900 def _run_is_done(self, file_list, parsed_url): |
955 # Both these are kept for hooks that are run as a separate tree traversal. | 901 # Both these are kept for hooks that are run as a separate tree traversal. |
956 self._file_list = file_list | 902 self._file_list = file_list |
957 self._parsed_url = parsed_url | 903 self._parsed_url = parsed_url |
958 self._processed = True | 904 self._processed = True |
959 | 905 |
960 @staticmethod | 906 @staticmethod |
(...skipping 17 matching lines...) Expand all Loading... | |
978 | 924 |
979 RunOnDeps() must have been called before to load the DEPS. | 925 RunOnDeps() must have been called before to load the DEPS. |
980 """ | 926 """ |
981 result = [] | 927 result = [] |
982 if not self.should_process or not self.recursion_limit: | 928 if not self.should_process or not self.recursion_limit: |
983 # Don't run the hook when it is above recursion_limit. | 929 # Don't run the hook when it is above recursion_limit. |
984 return result | 930 return result |
985 # If "--force" was specified, run all hooks regardless of what files have | 931 # If "--force" was specified, run all hooks regardless of what files have |
986 # changed. | 932 # changed. |
987 if self.deps_hooks: | 933 if self.deps_hooks: |
988 # TODO(maruel): If the user is using git or git-svn, then we don't know | 934 # TODO(maruel): If the user is using git, then we don't know |
989 # what files have changed so we always run all hooks. It'd be nice to fix | 935 # what files have changed so we always run all hooks. It'd be nice to fix |
990 # that. | 936 # that. |
991 if (options.force or | 937 if (options.force or |
992 isinstance(self.parsed_url, self.FileImpl) or | |
993 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or | 938 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or |
994 os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))): | 939 os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))): |
995 for hook_dict in self.deps_hooks: | 940 for hook_dict in self.deps_hooks: |
996 result.append(self.GetHookAction(hook_dict, [])) | 941 result.append(self.GetHookAction(hook_dict, [])) |
997 else: | 942 else: |
998 # Run hooks on the basis of whether the files from the gclient operation | 943 # Run hooks on the basis of whether the files from the gclient operation |
999 # match each hook's pattern. | 944 # match each hook's pattern. |
1000 for hook_dict in self.deps_hooks: | 945 for hook_dict in self.deps_hooks: |
1001 pattern = re.compile(hook_dict['pattern']) | 946 pattern = re.compile(hook_dict['pattern']) |
1002 matching_file_list = [ | 947 matching_file_list = [ |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1266 is actually checked out in %(checkout_path)s. | 1211 is actually checked out in %(checkout_path)s. |
1267 | 1212 |
1268 The .gclient file contains: | 1213 The .gclient file contains: |
1269 URL: %(expected_url)s (%(expected_scm)s) | 1214 URL: %(expected_url)s (%(expected_scm)s) |
1270 Cache mirror: %(mirror_string)s | 1215 Cache mirror: %(mirror_string)s |
1271 | 1216 |
1272 The local checkout in %(checkout_path)s reports: | 1217 The local checkout in %(checkout_path)s reports: |
1273 %(actual_url)s (%(actual_scm)s) | 1218 %(actual_url)s (%(actual_scm)s) |
1274 | 1219 |
1275 You should ensure that the URL listed in .gclient is correct and either change | 1220 You should ensure that the URL listed in .gclient is correct and either change |
1276 it or fix the checkout. If you're managing your own git checkout in | 1221 it or fix the checkout. |
1277 %(checkout_path)s but the URL in .gclient is for an svn repository, you probably | |
1278 want to set 'managed': False in .gclient. | |
1279 ''' % {'checkout_path': os.path.join(self.root_dir, dep.name), | 1222 ''' % {'checkout_path': os.path.join(self.root_dir, dep.name), |
1280 'expected_url': dep.url, | 1223 'expected_url': dep.url, |
1281 'expected_scm': gclient_scm.GetScmName(dep.url), | 1224 'expected_scm': gclient_scm.GetScmName(dep.url), |
1282 'mirror_string' : mirror_string, | 1225 'mirror_string' : mirror_string, |
1283 'actual_url': actual_url, | 1226 'actual_url': actual_url, |
1284 'actual_scm': gclient_scm.GetScmName(actual_url)}) | 1227 'actual_scm': gclient_scm.GetScmName(actual_url)}) |
1285 | 1228 |
1286 def SetConfig(self, content): | 1229 def SetConfig(self, content): |
1287 assert not self.dependencies | 1230 assert not self.dependencies |
1288 config_dict = {} | 1231 config_dict = {} |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1331 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 1274 raise gclient_utils.Error('Invalid .gclient file. Solution is ' |
1332 'incomplete: %s' % s) | 1275 'incomplete: %s' % s) |
1333 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) | 1276 self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', [])) |
1334 logging.info('SetConfig() done') | 1277 logging.info('SetConfig() done') |
1335 | 1278 |
1336 def SaveConfig(self): | 1279 def SaveConfig(self): |
1337 gclient_utils.FileWrite(os.path.join(self.root_dir, | 1280 gclient_utils.FileWrite(os.path.join(self.root_dir, |
1338 self._options.config_filename), | 1281 self._options.config_filename), |
1339 self.config_content) | 1282 self.config_content) |
1340 | 1283 |
1341 def MigrateConfigToGit(self, path, options): | |
1342 svn_url_re = re.compile('^(https?://src\.chromium\.org/svn|' | |
1343 'svn://svn\.chromium\.org/chrome)/' | |
1344 '(trunk|branches/[^/]+)/src') | |
1345 old_git_re = re.compile('^(https?://git\.chromium\.org|' | |
1346 'ssh://([a-zA-Z_][a-zA-Z0-9_-]*@)?' | |
1347 'gerrit\.chromium\.org(:2941[89])?)/' | |
1348 'chromium/src\.git') | |
1349 # Scan existing .gclient file for obsolete settings. It would be simpler | |
1350 # to traverse self.dependencies, but working with the AST allows the code to | |
1351 # dump an updated .gclient file that preserves the ordering of the original. | |
1352 a = ast.parse(self.config_content, options.config_filename, 'exec') | |
1353 modified = False | |
1354 solutions = [elem for elem in a.body if 'solutions' in | |
1355 [target.id for target in elem.targets]] | |
1356 if not solutions: | |
1357 return self | |
1358 solutions = solutions[-1] | |
1359 for solution in solutions.value.elts: | |
1360 # Check for obsolete URL's | |
1361 url_idx = ast_dict_index(solution, 'url') | |
1362 if url_idx == -1: | |
1363 continue | |
1364 url_val = solution.values[url_idx] | |
1365 if type(url_val) is not ast.Str: | |
1366 continue | |
1367 if (svn_url_re.match(url_val.s.strip())): | |
1368 raise gclient_utils.Error( | |
1369 """ | |
1370 The chromium code repository has migrated completely to git. | |
1371 Your SVN-based checkout is now obsolete; you need to create a brand-new | |
1372 git checkout by following these instructions: | |
1373 | |
1374 http://www.chromium.org/developers/how-tos/get-the-code | |
1375 """) | |
1376 if (old_git_re.match(url_val.s.strip())): | |
1377 url_val.s = CHROMIUM_SRC_URL | |
1378 modified = True | |
1379 | |
1380 # Ensure deps_file is set to .DEPS.git. We enforce this here to smooth | |
1381 # over switching between pre-git-migration and post-git-migration | |
1382 # revisions. | |
1383 # - For pre-migration revisions, .DEPS.git must be explicitly set. | |
1384 # - For post-migration revisions, .DEPS.git is not present, so gclient | |
1385 # will correctly fall back to DEPS. | |
1386 if url_val.s == CHROMIUM_SRC_URL: | |
1387 deps_file_idx = ast_dict_index(solution, 'deps_file') | |
1388 if deps_file_idx != -1: | |
1389 continue | |
1390 solution.keys.append(ast.Str('deps_file')) | |
1391 solution.values.append(ast.Str('.DEPS.git')) | |
1392 modified = True | |
1393 | |
1394 if not modified: | |
1395 return self | |
1396 | |
1397 print( | |
1398 """ | |
1399 WARNING: gclient detected an obsolete setting in your %s file. The file has | |
1400 been automagically updated. The previous version is available at %s.old. | |
1401 """ % (options.config_filename, options.config_filename)) | |
1402 | |
1403 # Replace existing .gclient with the updated version. | |
1404 # Return a new GClient instance based on the new content. | |
1405 new_content = ast2str(a) | |
1406 dot_gclient_fn = os.path.join(path, options.config_filename) | |
1407 try: | |
1408 os.rename(dot_gclient_fn, dot_gclient_fn + '.old') | |
1409 except OSError: | |
1410 pass | |
1411 with open(dot_gclient_fn, 'w') as fh: | |
1412 fh.write(new_content) | |
1413 client = GClient(path, options) | |
1414 client.SetConfig(new_content) | |
1415 return client | |
1416 | |
1417 @staticmethod | 1284 @staticmethod |
1418 def LoadCurrentConfig(options): | 1285 def LoadCurrentConfig(options): |
1419 """Searches for and loads a .gclient file relative to the current working | 1286 """Searches for and loads a .gclient file relative to the current working |
1420 dir. Returns a GClient object.""" | 1287 dir. Returns a GClient object.""" |
1421 if options.spec: | 1288 if options.spec: |
1422 client = GClient('.', options) | 1289 client = GClient('.', options) |
1423 client.SetConfig(options.spec) | 1290 client.SetConfig(options.spec) |
1424 else: | 1291 else: |
1425 if options.verbose: | 1292 if options.verbose: |
1426 print('Looking for %s starting from %s\n' % ( | 1293 print('Looking for %s starting from %s\n' % ( |
1427 options.config_filename, os.getcwd())) | 1294 options.config_filename, os.getcwd())) |
1428 path = gclient_utils.FindGclientRoot(os.getcwd(), options.config_filename) | 1295 path = gclient_utils.FindGclientRoot(os.getcwd(), options.config_filename) |
1429 if not path: | 1296 if not path: |
1430 return None | 1297 return None |
1431 client = GClient(path, options) | 1298 client = GClient(path, options) |
1432 client.SetConfig(gclient_utils.FileRead( | 1299 client.SetConfig(gclient_utils.FileRead( |
1433 os.path.join(path, options.config_filename))) | 1300 os.path.join(path, options.config_filename))) |
1434 client = client.MigrateConfigToGit(path, options) | |
1435 | 1301 |
1436 if (options.revisions and | 1302 if (options.revisions and |
1437 len(client.dependencies) > 1 and | 1303 len(client.dependencies) > 1 and |
1438 any('@' not in r for r in options.revisions)): | 1304 any('@' not in r for r in options.revisions)): |
1439 print( | 1305 print( |
1440 ('You must specify the full solution name like --revision %s@%s\n' | 1306 ('You must specify the full solution name like --revision %s@%s\n' |
1441 'when you have multiple solutions setup in your .gclient file.\n' | 1307 'when you have multiple solutions setup in your .gclient file.\n' |
1442 'Other solutions present are: %s.') % ( | 1308 'Other solutions present are: %s.') % ( |
1443 client.dependencies[0].name, | 1309 client.dependencies[0].name, |
1444 options.revisions[0], | 1310 options.revisions[0], |
(...skipping 14 matching lines...) Expand all Loading... | |
1459 | 1325 |
1460 def _SaveEntries(self): | 1326 def _SaveEntries(self): |
1461 """Creates a .gclient_entries file to record the list of unique checkouts. | 1327 """Creates a .gclient_entries file to record the list of unique checkouts. |
1462 | 1328 |
1463 The .gclient_entries file lives in the same directory as .gclient. | 1329 The .gclient_entries file lives in the same directory as .gclient. |
1464 """ | 1330 """ |
1465 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It | 1331 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It |
1466 # makes testing a bit too fun. | 1332 # makes testing a bit too fun. |
1467 result = 'entries = {\n' | 1333 result = 'entries = {\n' |
1468 for entry in self.root.subtree(False): | 1334 for entry in self.root.subtree(False): |
1469 # Skip over File() dependencies as we can't version them. | 1335 result += ' %s: %s,\n' % (pprint.pformat(entry.name), |
1470 if not isinstance(entry.parsed_url, self.FileImpl): | 1336 pprint.pformat(entry.parsed_url)) |
1471 result += ' %s: %s,\n' % (pprint.pformat(entry.name), | |
1472 pprint.pformat(entry.parsed_url)) | |
1473 result += '}\n' | 1337 result += '}\n' |
1474 file_path = os.path.join(self.root_dir, self._options.entries_filename) | 1338 file_path = os.path.join(self.root_dir, self._options.entries_filename) |
1475 logging.debug(result) | 1339 logging.debug(result) |
1476 gclient_utils.FileWrite(file_path, result) | 1340 gclient_utils.FileWrite(file_path, result) |
1477 | 1341 |
1478 def _ReadEntries(self): | 1342 def _ReadEntries(self): |
1479 """Read the .gclient_entries file for the given client. | 1343 """Read the .gclient_entries file for the given client. |
1480 | 1344 |
1481 Returns: | 1345 Returns: |
1482 A sequence of solution names, which will be empty if there is the | 1346 A sequence of solution names, which will be empty if there is the |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1592 e_dir = os.path.join(self.root_dir, entry_fixed) | 1456 e_dir = os.path.join(self.root_dir, entry_fixed) |
1593 # Use entry and not entry_fixed there. | 1457 # Use entry and not entry_fixed there. |
1594 if (entry not in entries and | 1458 if (entry not in entries and |
1595 (not any(path.startswith(entry + '/') for path in entries)) and | 1459 (not any(path.startswith(entry + '/') for path in entries)) and |
1596 os.path.exists(e_dir)): | 1460 os.path.exists(e_dir)): |
1597 # The entry has been removed from DEPS. | 1461 # The entry has been removed from DEPS. |
1598 scm = gclient_scm.CreateSCM( | 1462 scm = gclient_scm.CreateSCM( |
1599 prev_url, self.root_dir, entry_fixed, self.outbuf) | 1463 prev_url, self.root_dir, entry_fixed, self.outbuf) |
1600 | 1464 |
1601 # Check to see if this directory is now part of a higher-up checkout. | 1465 # Check to see if this directory is now part of a higher-up checkout. |
1602 # The directory might be part of a git OR svn checkout. | |
1603 scm_root = None | 1466 scm_root = None |
1604 scm_class = None | 1467 try: |
1605 for scm_class in (gclient_scm.scm.GIT, gclient_scm.scm.SVN): | 1468 scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(scm.checkout_path) |
1606 try: | 1469 except subprocess2.CalledProcessError: |
1607 scm_root = scm_class.GetCheckoutRoot(scm.checkout_path) | 1470 pass |
1608 except subprocess2.CalledProcessError: | 1471 if not scm_root: |
1609 pass | |
1610 if scm_root: | |
1611 break | |
1612 else: | |
1613 logging.warning('Could not find checkout root for %s. Unable to ' | 1472 logging.warning('Could not find checkout root for %s. Unable to ' |
1614 'determine whether it is part of a higher-level ' | 1473 'determine whether it is part of a higher-level ' |
1615 'checkout, so not removing.' % entry) | 1474 'checkout, so not removing.' % entry) |
1616 continue | 1475 continue |
1617 | 1476 |
1618 # This is to handle the case of third_party/WebKit migrating from | 1477 # This is to handle the case of third_party/WebKit migrating from |
1619 # being a DEPS entry to being part of the main project. | 1478 # being a DEPS entry to being part of the main project. |
1620 # If the subproject is a Git project, we need to remove its .git | 1479 # If the subproject is a Git project, we need to remove its .git |
1621 # folder. Otherwise git operations on that folder will have different | 1480 # folder. Otherwise git operations on that folder will have different |
1622 # effects depending on the current working directory. | 1481 # effects depending on the current working directory. |
1623 if scm_class == gclient_scm.scm.GIT and ( | 1482 if os.path.abspath(scm_root) == os.path.abspath(e_dir): |
1624 os.path.abspath(scm_root) == os.path.abspath(e_dir)): | |
1625 e_par_dir = os.path.join(e_dir, os.pardir) | 1483 e_par_dir = os.path.join(e_dir, os.pardir) |
1626 if scm_class.IsInsideWorkTree(e_par_dir): | 1484 if gclient_scm.scm.GIT.IsInsideWorkTree(e_par_dir): |
1627 par_scm_root = scm_class.GetCheckoutRoot(e_par_dir) | 1485 par_scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(e_par_dir) |
1628 # rel_e_dir : relative path of entry w.r.t. its parent repo. | 1486 # rel_e_dir : relative path of entry w.r.t. its parent repo. |
1629 rel_e_dir = os.path.relpath(e_dir, par_scm_root) | 1487 rel_e_dir = os.path.relpath(e_dir, par_scm_root) |
1630 if scm_class.IsDirectoryVersioned(par_scm_root, rel_e_dir): | 1488 if gclient_scm.scm.GIT.IsDirectoryVersioned( |
1489 par_scm_root, rel_e_dir): | |
1631 save_dir = scm.GetGitBackupDirPath() | 1490 save_dir = scm.GetGitBackupDirPath() |
1632 # Remove any eventual stale backup dir for the same project. | 1491 # Remove any eventual stale backup dir for the same project. |
1633 if os.path.exists(save_dir): | 1492 if os.path.exists(save_dir): |
1634 gclient_utils.rmtree(save_dir) | 1493 gclient_utils.rmtree(save_dir) |
1635 os.rename(os.path.join(e_dir, '.git'), save_dir) | 1494 os.rename(os.path.join(e_dir, '.git'), save_dir) |
1636 # When switching between the two states (entry/ is a subproject | 1495 # When switching between the two states (entry/ is a subproject |
1637 # -> entry/ is part of the outer project), it is very likely | 1496 # -> entry/ is part of the outer project), it is very likely |
1638 # that some files are changed in the checkout, unless we are | 1497 # that some files are changed in the checkout, unless we are |
1639 # jumping *exactly* across the commit which changed just DEPS. | 1498 # jumping *exactly* across the commit which changed just DEPS. |
1640 # In such case we want to cleanup any eventual stale files | 1499 # In such case we want to cleanup any eventual stale files |
1641 # (coming from the old subproject) in order to end up with a | 1500 # (coming from the old subproject) in order to end up with a |
1642 # clean checkout. | 1501 # clean checkout. |
1643 scm_class.CleanupDir(par_scm_root, rel_e_dir) | 1502 gclient_scm.scm.GIT.CleanupDir(par_scm_root, rel_e_dir) |
1644 assert not os.path.exists(os.path.join(e_dir, '.git')) | 1503 assert not os.path.exists(os.path.join(e_dir, '.git')) |
1645 print(('\nWARNING: \'%s\' has been moved from DEPS to a higher ' | 1504 print(('\nWARNING: \'%s\' has been moved from DEPS to a higher ' |
1646 'level checkout. The git folder containing all the local' | 1505 'level checkout. The git folder containing all the local' |
1647 ' branches has been saved to %s.\n' | 1506 ' branches has been saved to %s.\n' |
1648 'If you don\'t care about its state you can safely ' | 1507 'If you don\'t care about its state you can safely ' |
1649 'remove that folder to free up space.') % | 1508 'remove that folder to free up space.') % |
1650 (entry, save_dir)) | 1509 (entry, save_dir)) |
1651 continue | 1510 continue |
1652 | 1511 |
1653 if scm_root in full_entries: | 1512 if scm_root in full_entries: |
(...skipping 27 matching lines...) Expand all Loading... | |
1681 work_queue = gclient_utils.ExecutionQueue( | 1540 work_queue = gclient_utils.ExecutionQueue( |
1682 self._options.jobs, None, False, verbose=self._options.verbose) | 1541 self._options.jobs, None, False, verbose=self._options.verbose) |
1683 for s in self.dependencies: | 1542 for s in self.dependencies: |
1684 work_queue.enqueue(s) | 1543 work_queue.enqueue(s) |
1685 work_queue.flush({}, None, [], options=self._options) | 1544 work_queue.flush({}, None, [], options=self._options) |
1686 | 1545 |
1687 def GetURLAndRev(dep): | 1546 def GetURLAndRev(dep): |
1688 """Returns the revision-qualified SCM url for a Dependency.""" | 1547 """Returns the revision-qualified SCM url for a Dependency.""" |
1689 if dep.parsed_url is None: | 1548 if dep.parsed_url is None: |
1690 return None | 1549 return None |
1691 if isinstance(dep.parsed_url, self.FileImpl): | 1550 url, _ = gclient_utils.SplitUrlRevision(dep.parsed_url) |
1692 original_url = dep.parsed_url.file_location | |
1693 else: | |
1694 original_url = dep.parsed_url | |
1695 url, _ = gclient_utils.SplitUrlRevision(original_url) | |
1696 scm = gclient_scm.CreateSCM( | 1551 scm = gclient_scm.CreateSCM( |
1697 original_url, self.root_dir, dep.name, self.outbuf) | 1552 dep.parsed_url, self.root_dir, dep.name, self.outbuf) |
1698 if not os.path.isdir(scm.checkout_path): | 1553 if not os.path.isdir(scm.checkout_path): |
1699 return None | 1554 return None |
1700 return '%s@%s' % (url, scm.revinfo(self._options, [], None)) | 1555 return '%s@%s' % (url, scm.revinfo(self._options, [], None)) |
1701 | 1556 |
1702 if self._options.snapshot: | 1557 if self._options.snapshot: |
1703 new_gclient = '' | 1558 new_gclient = '' |
1704 # First level at .gclient | 1559 # First level at .gclient |
1705 for d in self.dependencies: | 1560 for d in self.dependencies: |
1706 entries = {} | 1561 entries = {} |
1707 def GrabDeps(dep): | 1562 def GrabDeps(dep): |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1770 return True | 1625 return True |
1771 | 1626 |
1772 @property | 1627 @property |
1773 def target_os(self): | 1628 def target_os(self): |
1774 return self._enforced_os | 1629 return self._enforced_os |
1775 | 1630 |
1776 | 1631 |
1777 #### gclient commands. | 1632 #### gclient commands. |
1778 | 1633 |
1779 | 1634 |
1780 def CMDcleanup(parser, args): | 1635 def CMDcleanup(parser, args): |
M-A Ruel
2016/10/05 21:13:33
Let's remove the command.
agable
2016/10/05 22:23:38
Will do in followup CL. (Removing it from gclient_
| |
1781 """Cleans up all working copies. | 1636 """DEPRECATED: SVN-only. Cleaned up all working copies. |
1782 | 1637 |
1783 Mostly svn-specific. Simply runs 'svn cleanup' for each module. | 1638 This is a no-op in Git. |
1784 """ | 1639 """ |
1785 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 1640 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
1786 help='override deps for the specified (comma-separated) ' | 1641 help='override deps for the specified (comma-separated) ' |
1787 'platform(s); \'all\' will process all deps_os ' | 1642 'platform(s); \'all\' will process all deps_os ' |
1788 'references') | 1643 'references') |
1789 (options, args) = parser.parse_args(args) | 1644 (options, args) = parser.parse_args(args) |
1790 client = GClient.LoadCurrentConfig(options) | 1645 client = GClient.LoadCurrentConfig(options) |
1791 if not client: | 1646 if not client: |
1792 raise gclient_utils.Error('client not configured; see \'gclient config\'') | 1647 raise gclient_utils.Error('client not configured; see \'gclient config\'') |
1793 if options.verbose: | 1648 if options.verbose: |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1956 return 0 | 1811 return 0 |
1957 | 1812 |
1958 | 1813 |
1959 @subcommand.epilog("""Example: | 1814 @subcommand.epilog("""Example: |
1960 gclient pack > patch.txt | 1815 gclient pack > patch.txt |
1961 generate simple patch for configured client and dependences | 1816 generate simple patch for configured client and dependences |
1962 """) | 1817 """) |
1963 def CMDpack(parser, args): | 1818 def CMDpack(parser, args): |
1964 """Generates a patch which can be applied at the root of the tree. | 1819 """Generates a patch which can be applied at the root of the tree. |
1965 | 1820 |
1966 Internally, runs 'svn diff'/'git diff' on each checked out module and | 1821 Internally, runs 'git diff' on each checked out module and |
1967 dependencies, and performs minimal postprocessing of the output. The | 1822 dependencies, and performs minimal postprocessing of the output. The |
1968 resulting patch is printed to stdout and can be applied to a freshly | 1823 resulting patch is printed to stdout and can be applied to a freshly |
1969 checked out tree via 'patch -p0 < patchfile'. | 1824 checked out tree via 'patch -p0 < patchfile'. |
1970 """ | 1825 """ |
1971 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 1826 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
1972 help='override deps for the specified (comma-separated) ' | 1827 help='override deps for the specified (comma-separated) ' |
1973 'platform(s); \'all\' will process all deps_os ' | 1828 'platform(s); \'all\' will process all deps_os ' |
1974 'references') | 1829 'references') |
1975 parser.remove_option('--jobs') | 1830 parser.remove_option('--jobs') |
1976 (options, args) = parser.parse_args(args) | 1831 (options, args) = parser.parse_args(args) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2011 | 1866 |
2012 JSON output format: | 1867 JSON output format: |
2013 If the --output-json option is specified, the following document structure will | 1868 If the --output-json option is specified, the following document structure will |
2014 be emitted to the provided file. 'null' entries may occur for subprojects which | 1869 be emitted to the provided file. 'null' entries may occur for subprojects which |
2015 are present in the gclient solution, but were not processed (due to custom_deps, | 1870 are present in the gclient solution, but were not processed (due to custom_deps, |
2016 os_deps, etc.) | 1871 os_deps, etc.) |
2017 | 1872 |
2018 { | 1873 { |
2019 "solutions" : { | 1874 "solutions" : { |
2020 "<name>": { # <name> is the posix-normalized path to the solution. | 1875 "<name>": { # <name> is the posix-normalized path to the solution. |
2021 "revision": [<svn rev int>|<git id hex string>|null], | 1876 "revision": [<git id hex string>|null], |
2022 "scm": ["svn"|"git"|null], | 1877 "scm": ["git"|null], |
2023 } | 1878 } |
2024 } | 1879 } |
2025 } | 1880 } |
2026 """) | 1881 """) |
2027 def CMDsync(parser, args): | 1882 def CMDsync(parser, args): |
2028 """Checkout/update all modules.""" | 1883 """Checkout/update all modules.""" |
2029 parser.add_option('-f', '--force', action='store_true', | 1884 parser.add_option('-f', '--force', action='store_true', |
2030 help='force update even for unchanged modules') | 1885 help='force update even for unchanged modules') |
2031 parser.add_option('-n', '--nohooks', action='store_true', | 1886 parser.add_option('-n', '--nohooks', action='store_true', |
2032 help='don\'t run hooks after the update is complete') | 1887 help='don\'t run hooks after the update is complete') |
2033 parser.add_option('-p', '--noprehooks', action='store_true', | 1888 parser.add_option('-p', '--noprehooks', action='store_true', |
2034 help='don\'t run pre-DEPS hooks', default=False) | 1889 help='don\'t run pre-DEPS hooks', default=False) |
2035 parser.add_option('-r', '--revision', action='append', | 1890 parser.add_option('-r', '--revision', action='append', |
2036 dest='revisions', metavar='REV', default=[], | 1891 dest='revisions', metavar='REV', default=[], |
2037 help='Enforces revision/hash for the solutions with the ' | 1892 help='Enforces revision/hash for the solutions with the ' |
2038 'format src@rev. The src@ part is optional and can be ' | 1893 'format src@rev. The src@ part is optional and can be ' |
2039 'skipped. -r can be used multiple times when .gclient ' | 1894 'skipped. -r can be used multiple times when .gclient ' |
2040 'has multiple solutions configured and will work even ' | 1895 'has multiple solutions configured and will work even ' |
2041 'if the src@ part is skipped. Note that specifying ' | 1896 'if the src@ part is skipped. Note that specifying ' |
2042 '--revision means your safesync_url gets ignored.') | 1897 '--revision means your safesync_url gets ignored.') |
2043 parser.add_option('--with_branch_heads', action='store_true', | 1898 parser.add_option('--with_branch_heads', action='store_true', |
2044 help='Clone git "branch_heads" refspecs in addition to ' | 1899 help='Clone git "branch_heads" refspecs in addition to ' |
2045 'the default refspecs. This adds about 1/2GB to a ' | 1900 'the default refspecs. This adds about 1/2GB to a ' |
2046 'full checkout. (git only)') | 1901 'full checkout. (git only)') |
2047 parser.add_option('--with_tags', action='store_true', | 1902 parser.add_option('--with_tags', action='store_true', |
2048 help='Clone git tags in addition to the default refspecs.') | 1903 help='Clone git tags in addition to the default refspecs.') |
2049 parser.add_option('-t', '--transitive', action='store_true', | 1904 parser.add_option('-t', '--transitive', action='store_true', |
M-A Ruel
2016/10/05 21:13:33
You can remove it now I think
agable
2016/10/05 22:23:38
Done
| |
2050 help='When a revision is specified (in the DEPS file or ' | 1905 help='DEPRECATED') |
2051 'with the command-line flag), transitively update ' | |
2052 'the dependencies to the date of the given revision. ' | |
2053 'Only supported for SVN repositories.') | |
2054 parser.add_option('-H', '--head', action='store_true', | 1906 parser.add_option('-H', '--head', action='store_true', |
2055 help='skips any safesync_urls specified in ' | 1907 help='skips any safesync_urls specified in ' |
2056 'configured solutions and sync to head instead') | 1908 'configured solutions and sync to head instead') |
2057 parser.add_option('-D', '--delete_unversioned_trees', action='store_true', | 1909 parser.add_option('-D', '--delete_unversioned_trees', action='store_true', |
2058 help='Deletes from the working copy any dependencies that ' | 1910 help='Deletes from the working copy any dependencies that ' |
2059 'have been removed since the last sync, as long as ' | 1911 'have been removed since the last sync, as long as ' |
2060 'there are no local modifications. When used with ' | 1912 'there are no local modifications. When used with ' |
2061 '--force, such dependencies are removed even if they ' | 1913 '--force, such dependencies are removed even if they ' |
2062 'have local modifications. When used with --reset, ' | 1914 'have local modifications. When used with --reset, ' |
2063 'all untracked directories are removed from the ' | 1915 'all untracked directories are removed from the ' |
2064 'working copy, excluding those which are explicitly ' | 1916 'working copy, excluding those which are explicitly ' |
2065 'ignored in the repository.') | 1917 'ignored in the repository.') |
2066 parser.add_option('-R', '--reset', action='store_true', | 1918 parser.add_option('-R', '--reset', action='store_true', |
2067 help='resets any local changes before updating (git only)') | 1919 help='resets any local changes before updating (git only)') |
2068 parser.add_option('-M', '--merge', action='store_true', | 1920 parser.add_option('-M', '--merge', action='store_true', |
2069 help='merge upstream changes instead of trying to ' | 1921 help='merge upstream changes instead of trying to ' |
2070 'fast-forward or rebase') | 1922 'fast-forward or rebase') |
2071 parser.add_option('-A', '--auto_rebase', action='store_true', | 1923 parser.add_option('-A', '--auto_rebase', action='store_true', |
2072 help='Automatically rebase repositories against local ' | 1924 help='Automatically rebase repositories against local ' |
2073 'checkout during update (git only).') | 1925 'checkout during update (git only).') |
2074 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 1926 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
2075 help='override deps for the specified (comma-separated) ' | 1927 help='override deps for the specified (comma-separated) ' |
2076 'platform(s); \'all\' will process all deps_os ' | 1928 'platform(s); \'all\' will process all deps_os ' |
2077 'references') | 1929 'references') |
2078 parser.add_option('-m', '--manually_grab_svn_rev', action='store_true', | 1930 parser.add_option('-m', '--manually_grab_svn_rev', action='store_true', |
M-A Ruel
2016/10/05 21:13:33
same
agable
2016/10/05 22:23:38
Done
| |
2079 help='Skip svn up whenever possible by requesting ' | 1931 help='DEPRECATED') |
2080 'actual HEAD revision from the repository') | |
2081 parser.add_option('--upstream', action='store_true', | 1932 parser.add_option('--upstream', action='store_true', |
2082 help='Make repo state match upstream branch.') | 1933 help='Make repo state match upstream branch.') |
2083 parser.add_option('--output-json', | 1934 parser.add_option('--output-json', |
2084 help='Output a json document to this path containing ' | 1935 help='Output a json document to this path containing ' |
2085 'summary information about the sync.') | 1936 'summary information about the sync.') |
2086 parser.add_option('--no-history', action='store_true', | 1937 parser.add_option('--no-history', action='store_true', |
2087 help='GIT ONLY - Reduces the size/time of the checkout at ' | 1938 help='GIT ONLY - Reduces the size/time of the checkout at ' |
2088 'the cost of no history. Requires Git 1.9+') | 1939 'the cost of no history. Requires Git 1.9+') |
2089 parser.add_option('--shallow', action='store_true', | 1940 parser.add_option('--shallow', action='store_true', |
2090 help='GIT ONLY - Do a shallow clone into the cache dir. ' | 1941 help='GIT ONLY - Do a shallow clone into the cache dir. ' |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2144 raise gclient_utils.Error('client not configured; see \'gclient config\'') | 1995 raise gclient_utils.Error('client not configured; see \'gclient config\'') |
2145 if options.verbose: | 1996 if options.verbose: |
2146 client.PrintLocationAndContents() | 1997 client.PrintLocationAndContents() |
2147 return client.RunOnDeps('diff', args) | 1998 return client.RunOnDeps('diff', args) |
2148 | 1999 |
2149 | 2000 |
2150 def CMDrevert(parser, args): | 2001 def CMDrevert(parser, args): |
2151 """Reverts all modifications in every dependencies. | 2002 """Reverts all modifications in every dependencies. |
2152 | 2003 |
2153 That's the nuclear option to get back to a 'clean' state. It removes anything | 2004 That's the nuclear option to get back to a 'clean' state. It removes anything |
2154 that shows up in svn status.""" | 2005 that shows up in git status.""" |
2155 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 2006 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
2156 help='override deps for the specified (comma-separated) ' | 2007 help='override deps for the specified (comma-separated) ' |
2157 'platform(s); \'all\' will process all deps_os ' | 2008 'platform(s); \'all\' will process all deps_os ' |
2158 'references') | 2009 'references') |
2159 parser.add_option('-n', '--nohooks', action='store_true', | 2010 parser.add_option('-n', '--nohooks', action='store_true', |
2160 help='don\'t run hooks after the revert is complete') | 2011 help='don\'t run hooks after the revert is complete') |
2161 parser.add_option('-p', '--noprehooks', action='store_true', | 2012 parser.add_option('-p', '--noprehooks', action='store_true', |
2162 help='don\'t run pre-DEPS hooks', default=False) | 2013 help='don\'t run pre-DEPS hooks', default=False) |
2163 parser.add_option('--upstream', action='store_true', | 2014 parser.add_option('--upstream', action='store_true', |
2164 help='Make repo state match upstream branch.') | 2015 help='Make repo state match upstream branch.') |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2196 options.force = True | 2047 options.force = True |
2197 options.nohooks = False | 2048 options.nohooks = False |
2198 return client.RunOnDeps('runhooks', args) | 2049 return client.RunOnDeps('runhooks', args) |
2199 | 2050 |
2200 | 2051 |
2201 def CMDrevinfo(parser, args): | 2052 def CMDrevinfo(parser, args): |
2202 """Outputs revision info mapping for the client and its dependencies. | 2053 """Outputs revision info mapping for the client and its dependencies. |
2203 | 2054 |
2204 This allows the capture of an overall 'revision' for the source tree that | 2055 This allows the capture of an overall 'revision' for the source tree that |
2205 can be used to reproduce the same tree in the future. It is only useful for | 2056 can be used to reproduce the same tree in the future. It is only useful for |
2206 'unpinned dependencies', i.e. DEPS/deps references without a svn revision | 2057 'unpinned dependencies', i.e. DEPS/deps references without a git hash. |
2207 number or a git hash. A git branch name isn't 'pinned' since the actual | 2058 A git branch name isn't 'pinned' since the actual commit can change. |
2208 commit can change. | |
2209 """ | 2059 """ |
2210 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 2060 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
2211 help='override deps for the specified (comma-separated) ' | 2061 help='override deps for the specified (comma-separated) ' |
2212 'platform(s); \'all\' will process all deps_os ' | 2062 'platform(s); \'all\' will process all deps_os ' |
2213 'references') | 2063 'references') |
2214 parser.add_option('-a', '--actual', action='store_true', | 2064 parser.add_option('-a', '--actual', action='store_true', |
2215 help='gets the actual checked out revisions instead of the ' | 2065 help='gets the actual checked out revisions instead of the ' |
2216 'ones specified in the DEPS and .gclient files') | 2066 'ones specified in the DEPS and .gclient files') |
2217 parser.add_option('-s', '--snapshot', action='store_true', | 2067 parser.add_option('-s', '--snapshot', action='store_true', |
2218 help='creates a snapshot .gclient file of the current ' | 2068 help='creates a snapshot .gclient file of the current ' |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2264 | 2114 |
2265 def __init__(self, **kwargs): | 2115 def __init__(self, **kwargs): |
2266 optparse.OptionParser.__init__( | 2116 optparse.OptionParser.__init__( |
2267 self, version='%prog ' + __version__, **kwargs) | 2117 self, version='%prog ' + __version__, **kwargs) |
2268 | 2118 |
2269 # Some arm boards have issues with parallel sync. | 2119 # Some arm boards have issues with parallel sync. |
2270 if platform.machine().startswith('arm'): | 2120 if platform.machine().startswith('arm'): |
2271 jobs = 1 | 2121 jobs = 1 |
2272 else: | 2122 else: |
2273 jobs = max(8, gclient_utils.NumLocalCpus()) | 2123 jobs = max(8, gclient_utils.NumLocalCpus()) |
2274 # cmp: 2013/06/19 | |
2275 # Temporary workaround to lower bot-load on SVN server. | |
2276 # Bypassed if a bot_update flag is detected. | |
2277 if (os.environ.get('CHROME_HEADLESS') == '1' and | |
2278 not os.path.exists('update.flag')): | |
2279 jobs = 1 | |
2280 | 2124 |
2281 self.add_option( | 2125 self.add_option( |
2282 '-j', '--jobs', default=jobs, type='int', | 2126 '-j', '--jobs', default=jobs, type='int', |
2283 help='Specify how many SCM commands can run in parallel; defaults to ' | 2127 help='Specify how many SCM commands can run in parallel; defaults to ' |
2284 '%default on this machine') | 2128 '%default on this machine') |
2285 self.add_option( | 2129 self.add_option( |
2286 '-v', '--verbose', action='count', default=0, | 2130 '-v', '--verbose', action='count', default=0, |
2287 help='Produces additional output for diagnostics. Can be used up to ' | 2131 help='Produces additional output for diagnostics. Can be used up to ' |
2288 'three times for more logging info.') | 2132 'three times for more logging info.') |
2289 self.add_option( | 2133 self.add_option( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2374 | 2218 |
2375 | 2219 |
2376 if '__main__' == __name__: | 2220 if '__main__' == __name__: |
2377 try: | 2221 try: |
2378 sys.exit(main(sys.argv[1:])) | 2222 sys.exit(main(sys.argv[1:])) |
2379 except KeyboardInterrupt: | 2223 except KeyboardInterrupt: |
2380 sys.stderr.write('interrupted\n') | 2224 sys.stderr.write('interrupted\n') |
2381 sys.exit(1) | 2225 sys.exit(1) |
2382 | 2226 |
2383 # vim: ts=2:sw=2:tw=80:et: | 2227 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |