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 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
7 | 7 |
8 """A git-command for integrating reviews on Rietveld.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
9 | 9 |
10 import json | 10 import json |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 dirty = RunGit(['diff-index', '--name-status', 'HEAD']) | 156 dirty = RunGit(['diff-index', '--name-status', 'HEAD']) |
157 if dirty: | 157 if dirty: |
158 print 'Cannot %s with a dirty tree. You must commit locally first.' % cmd | 158 print 'Cannot %s with a dirty tree. You must commit locally first.' % cmd |
159 print 'Uncommitted files: (git diff-index --name-status HEAD)' | 159 print 'Uncommitted files: (git diff-index --name-status HEAD)' |
160 print dirty[:4096] | 160 print dirty[:4096] |
161 if len(dirty) > 4096: | 161 if len(dirty) > 4096: |
162 print '... (run "git diff-index --name-status HEAD" to see full output).' | 162 print '... (run "git diff-index --name-status HEAD" to see full output).' |
163 return True | 163 return True |
164 return False | 164 return False |
165 | 165 |
| 166 |
166 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): | 167 def MatchSvnGlob(url, base_url, glob_spec, allow_wildcards): |
167 """Return the corresponding git ref if |base_url| together with |glob_spec| | 168 """Return the corresponding git ref if |base_url| together with |glob_spec| |
168 matches the full |url|. | 169 matches the full |url|. |
169 | 170 |
170 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). | 171 If |allow_wildcards| is true, |glob_spec| can contain wildcards (see below). |
171 """ | 172 """ |
172 fetch_suburl, as_ref = glob_spec.split(':') | 173 fetch_suburl, as_ref = glob_spec.split(':') |
173 if allow_wildcards: | 174 if allow_wildcards: |
174 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) | 175 glob_match = re.match('(.+/)?(\*|{[^/]*})(/.+)?', fetch_suburl) |
175 if glob_match: | 176 if glob_match: |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 if not self.branch: | 420 if not self.branch: |
420 self.branchref = RunGit(['symbolic-ref', 'HEAD']).strip() | 421 self.branchref = RunGit(['symbolic-ref', 'HEAD']).strip() |
421 self.branch = ShortBranchName(self.branchref) | 422 self.branch = ShortBranchName(self.branchref) |
422 return self.branch | 423 return self.branch |
423 | 424 |
424 def GetBranchRef(self): | 425 def GetBranchRef(self): |
425 """Returns the full branch name, e.g. 'refs/heads/master'.""" | 426 """Returns the full branch name, e.g. 'refs/heads/master'.""" |
426 self.GetBranch() # Poke the lazy loader. | 427 self.GetBranch() # Poke the lazy loader. |
427 return self.branchref | 428 return self.branchref |
428 | 429 |
429 def FetchUpstreamTuple(self): | 430 @staticmethod |
| 431 def FetchUpstreamTuple(branch): |
430 """Returns a tuple containg remote and remote ref, | 432 """Returns a tuple containg remote and remote ref, |
431 e.g. 'origin', 'refs/heads/master' | 433 e.g. 'origin', 'refs/heads/master' |
432 """ | 434 """ |
433 remote = '.' | 435 remote = '.' |
434 branch = self.GetBranch() | |
435 upstream_branch = RunGit(['config', 'branch.%s.merge' % branch], | 436 upstream_branch = RunGit(['config', 'branch.%s.merge' % branch], |
436 error_ok=True).strip() | 437 error_ok=True).strip() |
437 if upstream_branch: | 438 if upstream_branch: |
438 remote = RunGit(['config', 'branch.%s.remote' % branch]).strip() | 439 remote = RunGit(['config', 'branch.%s.remote' % branch]).strip() |
439 else: | 440 else: |
440 upstream_branch = RunGit(['config', 'rietveld.upstream-branch'], | 441 upstream_branch = RunGit(['config', 'rietveld.upstream-branch'], |
441 error_ok=True).strip() | 442 error_ok=True).strip() |
442 if upstream_branch: | 443 if upstream_branch: |
443 remote = RunGit(['config', 'rietveld.upstream-remote']).strip() | 444 remote = RunGit(['config', 'rietveld.upstream-remote']).strip() |
444 else: | 445 else: |
(...skipping 16 matching lines...) Expand all Loading... |
461 DieWithError("""Unable to determine default branch to diff against. | 462 DieWithError("""Unable to determine default branch to diff against. |
462 Either pass complete "git diff"-style arguments, like | 463 Either pass complete "git diff"-style arguments, like |
463 git cl upload origin/master | 464 git cl upload origin/master |
464 or verify this branch is set up to track another (via the --track argument to | 465 or verify this branch is set up to track another (via the --track argument to |
465 "git checkout -b ...").""") | 466 "git checkout -b ...").""") |
466 | 467 |
467 return remote, upstream_branch | 468 return remote, upstream_branch |
468 | 469 |
469 def GetUpstreamBranch(self): | 470 def GetUpstreamBranch(self): |
470 if self.upstream_branch is None: | 471 if self.upstream_branch is None: |
471 remote, upstream_branch = self.FetchUpstreamTuple() | 472 remote, upstream_branch = self.FetchUpstreamTuple(self.GetBranch()) |
472 if remote is not '.': | 473 if remote is not '.': |
473 upstream_branch = upstream_branch.replace('heads', 'remotes/' + remote) | 474 upstream_branch = upstream_branch.replace('heads', 'remotes/' + remote) |
474 self.upstream_branch = upstream_branch | 475 self.upstream_branch = upstream_branch |
475 return self.upstream_branch | 476 return self.upstream_branch |
476 | 477 |
477 def GetRemote(self): | 478 def GetRemoteBranch(self): |
478 if not self._remote: | 479 if not self._remote: |
479 self._remote = self.FetchUpstreamTuple()[0] | 480 remote, branch = None, self.GetBranch() |
480 if self._remote == '.': | 481 seen_branches = set() |
481 | 482 while branch not in seen_branches: |
| 483 seen_branches.add(branch) |
| 484 remote, branch = self.FetchUpstreamTuple(branch) |
| 485 branch = ShortBranchName(branch) |
| 486 if remote != '.' or branch.startswith('refs/remotes'): |
| 487 break |
| 488 else: |
482 remotes = RunGit(['remote'], error_ok=True).split() | 489 remotes = RunGit(['remote'], error_ok=True).split() |
483 if len(remotes) == 1: | 490 if len(remotes) == 1: |
484 self._remote, = remotes | 491 remote, = remotes |
485 elif 'origin' in remotes: | 492 elif 'origin' in remotes: |
486 self._remote = 'origin' | 493 remote = 'origin' |
487 logging.warning('Could not determine which remote this change is ' | 494 logging.warning('Could not determine which remote this change is ' |
488 'associated with, so defaulting to "%s". This may ' | 495 'associated with, so defaulting to "%s". This may ' |
489 'not be what you want. You may prevent this message ' | 496 'not be what you want. You may prevent this message ' |
490 'by running "git svn info" as documented here: %s', | 497 'by running "git svn info" as documented here: %s', |
491 self._remote, | 498 self._remote, |
492 GIT_INSTRUCTIONS_URL) | 499 GIT_INSTRUCTIONS_URL) |
493 else: | 500 else: |
494 logging.warn('Could not determine which remote this change is ' | 501 logging.warn('Could not determine which remote this change is ' |
495 'associated with. You may prevent this message by ' | 502 'associated with. You may prevent this message by ' |
496 'running "git svn info" as documented here: %s', | 503 'running "git svn info" as documented here: %s', |
497 GIT_INSTRUCTIONS_URL) | 504 GIT_INSTRUCTIONS_URL) |
| 505 branch = 'HEAD' |
| 506 if branch.startswith('refs/remotes'): |
| 507 self._remote = (remote, branch) |
| 508 else: |
| 509 self._remote = (remote, 'refs/remotes/%s/%s' % (remote, branch)) |
498 return self._remote | 510 return self._remote |
499 | 511 |
| 512 def GitSanityChecks(self, upstream_git_obj): |
| 513 """Checks git repo status and ensures diff is from local commits.""" |
| 514 |
| 515 # Verify the commit we're diffing against is in our current branch. |
| 516 upstream_sha = RunGit(['rev-parse', '--verify', upstream_git_obj]).strip() |
| 517 common_ancestor = RunGit(['merge-base', upstream_sha, 'HEAD']).strip() |
| 518 if upstream_sha != common_ancestor: |
| 519 print >> sys.stderr, ( |
| 520 'ERROR: %s is not in the current branch. You may need to rebase ' |
| 521 'your tracking branch' % upstream_sha) |
| 522 return False |
| 523 |
| 524 # List the commits inside the diff, and verify they are all local. |
| 525 commits_in_diff = RunGit( |
| 526 ['rev-list', '^%s' % upstream_sha, 'HEAD']).splitlines() |
| 527 code, remote_branch = RunGitWithCode(['config', 'gitcl.remotebranch']) |
| 528 remote_branch = remote_branch.strip() |
| 529 if code != 0: |
| 530 _, remote_branch = self.GetRemoteBranch() |
| 531 |
| 532 commits_in_remote = RunGit( |
| 533 ['rev-list', '^%s' % upstream_sha, remote_branch]).splitlines() |
| 534 |
| 535 common_commits = set(commits_in_diff) & set(commits_in_remote) |
| 536 if common_commits: |
| 537 print >> sys.stderr, ( |
| 538 'ERROR: Your diff contains %d commits already in %s.\n' |
| 539 'Run "git log --oneline %s..HEAD" to get a list of commits in ' |
| 540 'the diff. If you are using a custom git flow, you can override' |
| 541 ' the reference used for this check with "git config ' |
| 542 'gitcl.remotebranch <git-ref>".' % ( |
| 543 len(common_commits), remote_branch, upstream_git_obj)) |
| 544 return False |
| 545 return True |
| 546 |
500 def GetGitBaseUrlFromConfig(self): | 547 def GetGitBaseUrlFromConfig(self): |
501 """Return the configured base URL from branch.<branchname>.baseurl. | 548 """Return the configured base URL from branch.<branchname>.baseurl. |
502 | 549 |
503 Returns None if it is not set. | 550 Returns None if it is not set. |
504 """ | 551 """ |
505 return RunGit(['config', 'branch.%s.base-url' % self.GetBranch()], | 552 return RunGit(['config', 'branch.%s.base-url' % self.GetBranch()], |
506 error_ok=True).strip() | 553 error_ok=True).strip() |
507 | 554 |
508 def GetRemoteUrl(self): | 555 def GetRemoteUrl(self): |
509 """Return the configured remote URL, e.g. 'git://example.org/foo.git/'. | 556 """Return the configured remote URL, e.g. 'git://example.org/foo.git/'. |
510 | 557 |
511 Returns None if there is no remote. | 558 Returns None if there is no remote. |
512 """ | 559 """ |
513 remote = self.GetRemote() | 560 remote, _ = self.GetRemoteBranch() |
514 return RunGit(['config', 'remote.%s.url' % remote], error_ok=True).strip() | 561 return RunGit(['config', 'remote.%s.url' % remote], error_ok=True).strip() |
515 | 562 |
516 def GetIssue(self): | 563 def GetIssue(self): |
517 """Returns the issue number as a int or None if not set.""" | 564 """Returns the issue number as a int or None if not set.""" |
518 if not self.has_issue: | 565 if not self.has_issue: |
519 issue = RunGit(['config', self._IssueSetting()], error_ok=True).strip() | 566 issue = RunGit(['config', self._IssueSetting()], error_ok=True).strip() |
520 if issue: | 567 if issue: |
521 self.issue = int(issue) | 568 self.issue = int(issue) |
522 else: | 569 else: |
523 self.issue = None | 570 self.issue = None |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 if issue: | 647 if issue: |
601 RunGit(['config', self._IssueSetting(), str(issue)]) | 648 RunGit(['config', self._IssueSetting(), str(issue)]) |
602 if self.rietveld_server: | 649 if self.rietveld_server: |
603 RunGit(['config', self._RietveldServer(), self.rietveld_server]) | 650 RunGit(['config', self._RietveldServer(), self.rietveld_server]) |
604 else: | 651 else: |
605 RunGit(['config', '--unset', self._IssueSetting()]) | 652 RunGit(['config', '--unset', self._IssueSetting()]) |
606 self.SetPatchset(0) | 653 self.SetPatchset(0) |
607 self.has_issue = False | 654 self.has_issue = False |
608 | 655 |
609 def GetChange(self, upstream_branch, author): | 656 def GetChange(self, upstream_branch, author): |
| 657 if not self.GitSanityChecks(upstream_branch): |
| 658 DieWithError('\nGit sanity check failure') |
| 659 |
610 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() or '.' | 660 root = RunCommand(['git', 'rev-parse', '--show-cdup']).strip() or '.' |
611 absroot = os.path.abspath(root) | 661 absroot = os.path.abspath(root) |
612 | 662 |
613 # We use the sha1 of HEAD as a name of this change. | 663 # We use the sha1 of HEAD as a name of this change. |
614 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() | 664 name = RunCommand(['git', 'rev-parse', 'HEAD']).strip() |
615 # Need to pass a relative path for msysgit. | 665 # Need to pass a relative path for msysgit. |
616 try: | 666 try: |
617 files = scm.GIT.CaptureStatus([root], '.', upstream_branch) | 667 files = scm.GIT.CaptureStatus([root], '.', upstream_branch) |
618 except subprocess2.CalledProcessError: | 668 except subprocess2.CalledProcessError: |
619 DieWithError( | 669 DieWithError( |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 (options, args) = parser.parse_args(args) | 1061 (options, args) = parser.parse_args(args) |
1012 | 1062 |
1013 if not options.force and is_dirty_git_tree('presubmit'): | 1063 if not options.force and is_dirty_git_tree('presubmit'): |
1014 print 'use --force to check even if tree is dirty.' | 1064 print 'use --force to check even if tree is dirty.' |
1015 return 1 | 1065 return 1 |
1016 | 1066 |
1017 cl = Changelist() | 1067 cl = Changelist() |
1018 if args: | 1068 if args: |
1019 base_branch = args[0] | 1069 base_branch = args[0] |
1020 else: | 1070 else: |
1021 # Default to diffing against the "upstream" branch. | 1071 # Default to diffing against the common ancestor of the upstream branch. |
1022 base_branch = cl.GetUpstreamBranch() | 1072 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() |
1023 | 1073 |
1024 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, | 1074 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, |
1025 may_prompt=False, verbose=options.verbose, | 1075 may_prompt=False, verbose=options.verbose, |
1026 author=None) | 1076 author=None) |
1027 return 0 | 1077 return 0 |
1028 | 1078 |
1029 | 1079 |
1030 def AddChangeIdToCommitMessage(options, args): | 1080 def AddChangeIdToCommitMessage(options, args): |
1031 """Re-commits using the current message, assumes the commit hook is in | 1081 """Re-commits using the current message, assumes the commit hook is in |
1032 place. | 1082 place. |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 'See http://goo.gl/JGg0Z for details.\n') | 1259 'See http://goo.gl/JGg0Z for details.\n') |
1210 | 1260 |
1211 if is_dirty_git_tree('upload'): | 1261 if is_dirty_git_tree('upload'): |
1212 return 1 | 1262 return 1 |
1213 | 1263 |
1214 cl = Changelist() | 1264 cl = Changelist() |
1215 if args: | 1265 if args: |
1216 # TODO(ukai): is it ok for gerrit case? | 1266 # TODO(ukai): is it ok for gerrit case? |
1217 base_branch = args[0] | 1267 base_branch = args[0] |
1218 else: | 1268 else: |
1219 # Default to diffing against the "upstream" branch. | 1269 # Default to diffing against common ancestor of upstream branch |
1220 base_branch = cl.GetUpstreamBranch() | 1270 base_branch = RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip() |
1221 args = [base_branch + "..."] | 1271 args = [base_branch] |
1222 | 1272 |
1223 if not options.bypass_hooks: | 1273 if not options.bypass_hooks: |
1224 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, | 1274 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, |
1225 may_prompt=not options.force, | 1275 may_prompt=not options.force, |
1226 verbose=options.verbose, | 1276 verbose=options.verbose, |
1227 author=None) | 1277 author=None) |
1228 if not hook_results.should_continue(): | 1278 if not hook_results.should_continue(): |
1229 return 1 | 1279 return 1 |
1230 if not options.reviewers and hook_results.reviewers: | 1280 if not options.reviewers and hook_results.reviewers: |
1231 options.reviewers = hook_results.reviewers | 1281 options.reviewers = hook_results.reviewers |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 base_svn_head += '^1' | 1353 base_svn_head += '^1' |
1304 | 1354 |
1305 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head]) | 1355 extra_commits = RunGit(['rev-list', '^' + svn_head, base_svn_head]) |
1306 if extra_commits: | 1356 if extra_commits: |
1307 print ('This branch has %d additional commits not upstreamed yet.' | 1357 print ('This branch has %d additional commits not upstreamed yet.' |
1308 % len(extra_commits.splitlines())) | 1358 % len(extra_commits.splitlines())) |
1309 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' | 1359 print ('Upstream "%s" or rebase this branch on top of the upstream trunk ' |
1310 'before attempting to %s.' % (base_branch, cmd)) | 1360 'before attempting to %s.' % (base_branch, cmd)) |
1311 return 1 | 1361 return 1 |
1312 | 1362 |
| 1363 base_branch = RunGit(['merge-base', base_branch, 'HEAD']).strip() |
1313 if not options.bypass_hooks: | 1364 if not options.bypass_hooks: |
1314 author = None | 1365 author = None |
1315 if options.contributor: | 1366 if options.contributor: |
1316 author = re.search(r'\<(.*)\>', options.contributor).group(1) | 1367 author = re.search(r'\<(.*)\>', options.contributor).group(1) |
1317 hook_results = cl.RunHook( | 1368 hook_results = cl.RunHook( |
1318 committing=True, | 1369 committing=True, |
1319 upstream_branch=base_branch, | 1370 upstream_branch=base_branch, |
1320 may_prompt=not options.force, | 1371 may_prompt=not options.force, |
1321 verbose=options.verbose, | 1372 verbose=options.verbose, |
1322 author=author) | 1373 author=author) |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 RunGit(['commit', '--author', options.contributor, '-m', description]) | 1447 RunGit(['commit', '--author', options.contributor, '-m', description]) |
1397 else: | 1448 else: |
1398 RunGit(['commit', '-m', description]) | 1449 RunGit(['commit', '-m', description]) |
1399 if base_has_submodules: | 1450 if base_has_submodules: |
1400 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() | 1451 cherry_pick_commit = RunGit(['rev-list', 'HEAD^!']).rstrip() |
1401 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) | 1452 RunGit(['branch', CHERRY_PICK_BRANCH, svn_head]) |
1402 RunGit(['checkout', CHERRY_PICK_BRANCH]) | 1453 RunGit(['checkout', CHERRY_PICK_BRANCH]) |
1403 RunGit(['cherry-pick', cherry_pick_commit]) | 1454 RunGit(['cherry-pick', cherry_pick_commit]) |
1404 if cmd == 'push': | 1455 if cmd == 'push': |
1405 # push the merge branch. | 1456 # push the merge branch. |
1406 remote, branch = cl.FetchUpstreamTuple() | 1457 remote, branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
1407 retcode, output = RunGitWithCode( | 1458 retcode, output = RunGitWithCode( |
1408 ['push', '--porcelain', remote, 'HEAD:%s' % branch]) | 1459 ['push', '--porcelain', remote, 'HEAD:%s' % branch]) |
1409 logging.debug(output) | 1460 logging.debug(output) |
1410 else: | 1461 else: |
1411 # dcommit the merge branch. | 1462 # dcommit the merge branch. |
1412 retcode, output = RunGitWithCode(['svn', 'dcommit', | 1463 retcode, output = RunGitWithCode(['svn', 'dcommit', |
1413 '-C%s' % options.similarity, | 1464 '-C%s' % options.similarity, |
1414 '--no-rebase', '--rmdir']) | 1465 '--no-rebase', '--rmdir']) |
1415 finally: | 1466 finally: |
1416 # And then swap back to the original branch and clean up. | 1467 # And then swap back to the original branch and clean up. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1649 cl = Changelist() | 1700 cl = Changelist() |
1650 if not cl.GetIssue(): | 1701 if not cl.GetIssue(): |
1651 parser.error('Need to upload first') | 1702 parser.error('Need to upload first') |
1652 | 1703 |
1653 if not options.name: | 1704 if not options.name: |
1654 options.name = cl.GetBranch() | 1705 options.name = cl.GetBranch() |
1655 | 1706 |
1656 # Process --bot and --testfilter. | 1707 # Process --bot and --testfilter. |
1657 if not options.bot: | 1708 if not options.bot: |
1658 # Get try slaves from PRESUBMIT.py files if not specified. | 1709 # Get try slaves from PRESUBMIT.py files if not specified. |
1659 change = cl.GetChange(cl.GetUpstreamBranch(), None) | 1710 change = cl.GetChange( |
| 1711 RunGit(['merge-base', cl.GetUpstreamBranch(), 'HEAD']).strip(), |
| 1712 None) |
1660 options.bot = presubmit_support.DoGetTrySlaves( | 1713 options.bot = presubmit_support.DoGetTrySlaves( |
1661 change, | 1714 change, |
1662 change.LocalPaths(), | 1715 change.LocalPaths(), |
1663 settings.GetRoot(), | 1716 settings.GetRoot(), |
1664 None, | 1717 None, |
1665 None, | 1718 None, |
1666 options.verbose, | 1719 options.verbose, |
1667 sys.stdout) | 1720 sys.stdout) |
1668 if not options.bot: | 1721 if not options.bot: |
1669 parser.error('No default try builder to try, use --bot') | 1722 parser.error('No default try builder to try, use --bot') |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1809 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1862 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1810 | 1863 |
1811 # Not a known command. Default to help. | 1864 # Not a known command. Default to help. |
1812 GenUsage(parser, 'help') | 1865 GenUsage(parser, 'help') |
1813 return CMDhelp(parser, argv) | 1866 return CMDhelp(parser, argv) |
1814 | 1867 |
1815 | 1868 |
1816 if __name__ == '__main__': | 1869 if __name__ == '__main__': |
1817 fix_encoding.fix_encoding() | 1870 fix_encoding.fix_encoding() |
1818 sys.exit(main(sys.argv[1:])) | 1871 sys.exit(main(sys.argv[1:])) |
OLD | NEW |