]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'yz/p4-py3'
authorJunio C Hamano <gitster@pobox.com>
Wed, 25 Mar 2020 20:57:43 +0000 (13:57 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Mar 2020 20:57:43 +0000 (13:57 -0700)
Update "git p4" to work with Python 3.

* yz/p4-py3:
  ci: use python3 in linux-gcc and osx-gcc and python2 elsewhere
  git-p4: use python3's input() everywhere
  git-p4: simplify regex pattern generation for parsing diff-tree
  git-p4: use dict.items() iteration for python3 compatibility
  git-p4: use functools.reduce instead of reduce
  git-p4: fix freezing while waiting for fast-import progress
  git-p4: use marshal format version 2 when sending to p4
  git-p4: open .gitp4-usercache.txt in text mode
  git-p4: convert path to unicode before processing them
  git-p4: encode/decode communication with git for python3
  git-p4: encode/decode communication with p4 for python3
  git-p4: remove string type aliasing
  git-p4: change the expansion test from basestring to list
  git-p4: make python2.7 the oldest supported version

1  2 
git-p4.py

diff --cc git-p4.py
index 9a71a6690db35d674456c677be1212e44e57a582,17f72f430905523b2ecb8a2cd62fd2fb6043e9f7..1fe03cd3392f209ce985f1446ac403c8c0dca9bb
+++ b/git-p4.py
@@@ -7,18 -7,9 +7,17 @@@
  #            2007 Trolltech ASA
  # License: MIT <http://www.opensource.org/licenses/mit-license.php>
  #
 +# pylint: disable=invalid-name,missing-docstring,too-many-arguments,broad-except
 +# pylint: disable=no-self-use,wrong-import-position,consider-iterating-dictionary
 +# pylint: disable=wrong-import-order,unused-import,too-few-public-methods
 +# pylint: disable=too-many-lines,ungrouped-imports,fixme,too-many-locals
 +# pylint: disable=line-too-long,bad-whitespace,superfluous-parens
 +# pylint: disable=too-many-statements,too-many-instance-attributes
 +# pylint: disable=too-many-branches,too-many-nested-blocks
 +#
  import sys
- if sys.hexversion < 0x02040000:
-     # The limiter is the subprocess module
-     sys.stderr.write("git-p4: requires Python 2.4 or later.\n")
+ if sys.version_info.major < 3 and sys.version_info.minor < 7:
+     sys.stderr.write("git-p4: requires Python 2.7 or later.\n")
      sys.exit(1)
  import os
  import optparse
@@@ -178,21 -146,36 +157,51 @@@ def die(msg)
          sys.stderr.write(msg + "\n")
          sys.exit(1)
  
-         response = raw_input(prompt_text).strip().lower()
 +def prompt(prompt_text):
 +    """ Prompt the user to choose one of the choices
 +
 +    Choices are identified in the prompt_text by square brackets around
 +    a single letter option.
 +    """
 +    choices = set(m.group(1) for m in re.finditer(r"\[(.)\]", prompt_text))
 +    while True:
++        response = input(prompt_text).strip().lower()
 +        if not response:
 +            continue
 +        response = response[0]
 +        if response in choices:
 +            return response
 +
+ # We need different encoding/decoding strategies for text data being passed
+ # around in pipes depending on python version
+ if bytes is not str:
+     # For python3, always encode and decode as appropriate
+     def decode_text_stream(s):
+         return s.decode() if isinstance(s, bytes) else s
+     def encode_text_stream(s):
+         return s.encode() if isinstance(s, str) else s
+ else:
+     # For python2.7, pass read strings as-is, but also allow writing unicode
+     def decode_text_stream(s):
+         return s
+     def encode_text_stream(s):
+         return s.encode('utf_8') if isinstance(s, unicode) else s
+ def decode_path(path):
+     """Decode a given string (bytes or otherwise) using configured path encoding options
+     """
+     encoding = gitConfig('git-p4.pathEncoding') or 'utf_8'
+     if bytes is not str:
+         return path.decode(encoding, errors='replace') if isinstance(path, bytes) else path
+     else:
+         try:
+             path.decode('ascii')
+         except:
+             path = path.decode(encoding, errors='replace')
+             if verbose:
+                 print('Path with non-ASCII characters detected. Used {} to decode: {}'.format(encoding, path))
+         return path
  def write_pipe(c, stdin):
      if verbose:
          sys.stderr.write('Writing pipe: %s\n' % str(c))
@@@ -3635,9 -3573,16 +3671,18 @@@ class P4Sync(Command, P4UserMap)
          self.gitStream = self.importProcess.stdin
          self.gitError = self.importProcess.stderr
  
+         if bytes is not str:
+             # Wrap gitStream.write() so that it can be called using `str` arguments
+             def make_encoded_write(write):
+                 def encoded_write(s):
+                     return write(s.encode() if isinstance(s, str) else s)
+                 return encoded_write
+             self.gitStream.write = make_encoded_write(self.gitStream.write)
      def closeStreams(self):
 +        if self.gitStream is None:
 +            return
          self.gitStream.close()
          if self.importProcess.wait() != 0:
              die("fast-import failed: %s" % self.gitError.read())