git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [RFC/PATCH 2/8 v3] git_remote_helpers: fix input when running under Python 3

From
John Keeping <john@keeping.me.uk>
Date
Jan 16, 2013, 09:45 UTC
Message-ID
<20130116094418.GA9089@river>
In-Reply-To
<20130116000316.GA26999@padd.com>
On Tue, Jan 15, 2013 at 07:03:16PM -0500, Pete Wyckoff wrote:
Show 63 quoted lines
> john@keeping.me.uk wrote on Tue, 15 Jan 2013 22:40 +0000:
>> This is what keeping the refs as byte strings looks like.
> 
> As John knows, it is not possible to interpret text from a byte
> string without talking about the character encoding.
> 
> Git is (largely) a C program and uses the character set defined
> in the C standard, which is a subset of ASCII.  But git does
> "math" on strings, like this snippet that takes something from
> argv[] and prepends "refs/heads/":
> 
>     strcpy(refname, "refs/heads/");
>     strcpy(refname + strlen("refs/heads/"), ret->name);
> 
> The result doesn't talk about what character set it is using,
> but because it combines a prefix from ASCII with its input,
> git makes the assumption that the input is ASCII-compatible.
> 
> If you feed a UTF-16 string in argv, e.g.
> 
>     $ echo master | iconv -f ascii -t utf16 | xargs git branch
>     xargs: Warning: a NUL character occurred in the input.  It cannot be passed through in the argument list.  Did you mean to use the --null option?
>     fatal: Not a valid object name: ''.
> 
> you get an error about NUL, and not the branch you hoped for.
> Git assumes that the input character set contains roughly ASCII
> in byte positions 0..127.
> 
> That's one small reason why the useful character encodings put
> ASCII in the 0..127 range, including utf-8, big5 and shift-jis.
> ASCII is indeed special due to its legacy, and both C and Python
> recognize this.
> 
>> diff --git a/git_remote_helpers/git/importer.py b/git_remote_helpers/git/importer.py
>> @@ -18,13 +18,16 @@ class GitImporter(object):
>>  
>>      def get_refs(self, gitdir):
>>          """Returns a dictionary with refs.
>> +
>> +        Note that the keys in the returned dictionary are byte strings as
>> +        read from git.
>>          """
>>          args = ["git", "--git-dir=" + gitdir, "for-each-ref", "refs/heads"]
>> -        lines = check_output(args).strip().split('\n')
>> +        lines = check_output(args).strip().split('\n'.encode('utf-8'))
>>          refs = {}
>>          for line in lines:
>> -            value, name = line.split(' ')
>> -            name = name.strip('commit\t')
>> +            value, name = line.split(' '.encode('utf-8'))
>> +            name = name.strip('commit\t'.encode('utf-8'))
>>              refs[name] = value
>>          return refs
> 
> I'd suggest for this Python conundrum using byte-string literals, e.g.:
> 
>         lines = check_output(args).strip().split(b'\n')
> 	value, name = line.split(b' ')
> 	name = name.strip(b'commit\t')
> 
> Essentially identical to what you have, but avoids naming "utf-8" as
> the encoding.  It instead relies on Python's interpretation of
> ASCII characters in string context, which is exactly what C does.

The problem is that AFAICT the byte-string prefix is only available in Python 2.7 and later (compare [1] and [2]). I think we need this more convoluted code if we want to keep supporting Python 2.6 (although perhaps 'ascii' would be a better choice than 'utf-8').

[1] http://docs.python.org/2.6/reference/lexical_analysis.html#literals [2] http://docs.python.org/2.7/reference/lexical_analysis.html#literals

John
Previous: Pete WyckoffNext: Pete Wyckoff
Message 14 of 53 in “Initial support for Python 3”
  1. 0/8 Initial support for Python 3John Keeping, Jan 12, 2013
  2. 1/8 git_remote_helpers: Allow building with Python 3John Keeping, Jan 12, 2013
  3. 2/8 git_remote_helpers: fix input when running under Python 3John Keeping, Jan 12, 2013
  4. Michael HaggertyJan 13, 2013
  5. John KeepingJan 13, 2013
  6. Michael HaggertyJan 14, 2013
  7. John KeepingJan 14, 2013
  8. 2/8 git_remote_helpers: fix input when running under Python 3John Keeping, Jan 15, 2013
  9. Junio C HamanoJan 15, 2013
  10. John KeepingJan 15, 2013
  11. Junio C HamanoJan 15, 2013
  12. 2/8 git_remote_helpers: fix input when running under Python 3John Keeping, Jan 15, 2013
  13. Pete WyckoffJan 16, 2013
  14. John KeepingJan 16, 2013
  15. Pete WyckoffJan 17, 2013
  16. 3/8 git_remote_helpers: Force rebuild if python version changesJohn Keeping, Jan 12, 2013
  17. Pete WyckoffJan 12, 2013
  18. John KeepingJan 13, 2013
  19. Pete WyckoffJan 13, 2013
  20. John KeepingJan 13, 2013
  21. John KeepingJan 15, 2013
  22. Pete WyckoffJan 17, 2013
  23. 4/8 git_remote_helpers: Use 2to3 if building with Python 3John Keeping, Jan 12, 2013
  24. 5/8 svn-fe: allow svnrdump_sim.py to run with Python 3John Keeping, Jan 12, 2013
  25. 6/8 git-remote-testpy: hash bytes explicitlyJohn Keeping, Jan 12, 2013
  26. 7/8 git-remote-testpy: don't do unbuffered text I/OJohn Keeping, Jan 12, 2013
  27. 8/8 git-remote-testpy: call print as a functionJohn Keeping, Jan 12, 2013
  28. Pete WyckoffJan 12, 2013
  29. John KeepingJan 13, 2013
  30. John KeepingJan 13, 2013
  31. Pete WyckoffJan 13, 2013
  32. John KeepingJan 13, 2013
  33. 0/8 Initial Python 3 supportJohn Keeping, Jan 17, 2013
  34. 1/8 git_remote_helpers: allow building with Python 3John Keeping, Jan 17, 2013
  35. 2/8 git_remote_helpers: fix input when running under Python 3John Keeping, Jan 17, 2013
  36. 3/8 git_remote_helpers: force rebuild if python version changesJohn Keeping, Jan 17, 2013
  37. 4/8 git_remote_helpers: use 2to3 if building with Python 3John Keeping, Jan 17, 2013
  38. Sverre RabbelierJan 18, 2013
  39. John KeepingJan 18, 2013
  40. Sverre RabbelierJan 19, 2013
  41. 5/8 svn-fe: allow svnrdump_sim.py to run with Python 3John Keeping, Jan 17, 2013
  42. 6/8 git-remote-testpy: hash bytes explicitlyJohn Keeping, Jan 17, 2013
  43. Junio C HamanoJan 17, 2013
  44. Junio C HamanoJan 17, 2013
  45. John KeepingJan 17, 2013
  46. John KeepingJan 17, 2013
  47. Junio C HamanoJan 17, 2013
  48. John KeepingJan 17, 2013
  49. Junio C HamanoJan 17, 2013
  50. 7/8 git-remote-testpy: don't do unbuffered text I/OJohn Keeping, Jan 17, 2013
  51. Sverre RabbelierJan 18, 2013
  52. 8/8 git-remote-testpy: call print as a functionJohn Keeping, Jan 17, 2013
  53. Sverre RabbelierJan 18, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.