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

Re: [PATCH v1] convert: add support for 'encoding' attribute

From
Lars Schneider <larsxschneider@gmail.com>
Date
Dec 18, 2017, 10:54 UTC
Message-ID
<D1E22F0E-EC10-4133-9177-AE20F398A8AC@gmail.com>
In-Reply-To
<20171215095838.GA3567@sigill.intra.peff.net>
Show 47 quoted lines
> On 15 Dec 2017, at 10:58, Jeff King <peff@peff.net> wrote:
> 
> On Mon, Dec 11, 2017 at 04:50:23PM +0100, lars.schneider@autodesk.com wrote:
> 
>> From: Lars Schneider <larsxschneider@gmail.com>
>> 
>> Git and its tools (e.g. git diff) expect all text files in UTF-8
>> encoding. Git will happily accept content in all other encodings, too,
>> but it might not be able to process the text (e.g. viewing diffs or
>> changing line endings).
>> 
>> Add an attribute to tell Git what encoding the user has defined for a
>> given file. If the content is added to the index, then Git converts the
>> content to a canonical UTF-8 representation. On checkout Git will
>> reverse the conversion.
> 
> This made me wonder what happens when you have a file that _was_ utf16,
> and then you later convert it to utf8 and add a .gitattributes entry.
> 
> I tried this with your patch:
> 
>  git init repo
>  cd repo
> 
>  echo foo | iconv -t utf16 >file
>  git add file
>  git commit -m utf16
> 
>  echo 'file encoding=utf16' >.gitattributes
>  touch file ;# make it stat-dirty
>  git commit -m convert
> 
>  git checkout HEAD^
> 
> That works OK, because we try to read the attributes from the
> destination tree for a checkout. If you do this:
> 
>  echo 'file encoding=utf16' >.git/info/attributes
>  git checkout HEAD^
> 
> then we get:
> 
>  warning: failed to encode 'file' from utf-8 to utf16
> 
> At least it figured out that it couldn't convert the content. It's
> slightly troubling that it would try in the first place, though; are
> there encoding pairs where we might accidentally generate nonsense?

At this point we interpret utf-16 content as utf-8 and try to convert it to utf-16. That of course fails because utf-16 content is no valid utf-8. How could we stop trying that? How could Git possibly know what kind of encoding is used (apart from our new hint in gitattributes)?

I asked myself the question about nonsense encoding pairs, too. That was the reason I added the "X -> UTF-8 -> Y && X == Y" check on Git add. However, with ".git/info/attributes" you could circumvent that check and probably generate nonsense.

Show 43 quoted lines
> It _should_ be uncommon, I think, to have a repo-level attribute set
> like that. It's very common for us to use whatever happens to be in the
> checked-out .gitattributes for some attributes (e.g., when doing a diff
> of an older commit), but I think for checkout-related ones it's not.  So
> I think it may generally work in practice. And certainly the line-ending
> code would share any similar problems, but at least there the result is
> less confusing than mojibake.
> 
> Playing around, I also managed to do this:
> 
>  echo 'file encoding=utf16' >.gitattributes
>  echo foo >file
> 
>  # I did these with an old version of git that didn't
>  # support the new attribute, so they blindly added the utf8 content.
>  git add .
>  git commit -m convert
> 
>  git.compile checkout HEAD^
> 
> which yielded:
> 
>  fatal: encoding 'file' from utf16 to utf-8 and back is not the same
> 
> Now obviously my situation is somewhat nonsense. I was trying to force
> the in-repo representation to utf8, but ended up with a mismatched
> working tree file. But what's somewhat troubling is that I couldn't
> checkout _away_ from that state due to the die() in convert_to_git().
> Which is in turn just there as part of refresh_index().
> 
> And indeed, other commands hit the same problem:
> 
>  $ git.compile diff
>  fatal: encoding 'file' from utf16 to utf-8 and back is not the same
> 
>  $ git.compile checkout -f
>  fatal: encoding 'file' from utf16 to utf-8 and back is not the same
> 
> It may make sense to die() during "git add ." (since we're actually
> changing the index entry, and we don't want to put nonsense into a
> tree). But I'm not sure it's the best thing for operations which just
> want to read the content. For them, perhaps it would be more appropriate
> to issue a warning and return the untouched content.

Absolutely! Thanks for spotting this. I will try to run die() only on "git add" in v2.

- Lars
Previous: Jeff KingNext: Jeff King
Message 29 of 36 in “convert: add support for 'encoding' attribute”
  1. convert: add support for 'encoding' attributelars.schneider@autodesk.com, Dec 11, 2017
  2. Eric SunshineDec 11, 2017
  3. Lars SchneiderDec 11, 2017
  4. Eric SunshineDec 11, 2017
  5. Lars SchneiderDec 12, 2017
  6. Johannes SixtDec 11, 2017
  7. Lars SchneiderDec 11, 2017
  8. Junio C HamanoDec 12, 2017
  9. Johannes SixtDec 12, 2017
  10. Lars SchneiderDec 12, 2017
  11. Junio C HamanoDec 12, 2017
  12. Lars SchneiderDec 13, 2017
  13. Junio C HamanoDec 13, 2017
  14. Lars SchneiderDec 13, 2017
  15. Junio C HamanoDec 14, 2017
  16. Johannes SixtDec 12, 2017
  17. Torsten BögershausenDec 18, 2017
  18. Jeff KingDec 18, 2017
  19. Torsten BögershausenDec 23, 2017
  20. 0/2 git diff --UTF-8tboegi@web.de, Dec 29, 2017
  21. 2/2 git diff: Allow to reencode into UTF-8tboegi@web.de, Dec 29, 2017
  22. 1/2 convert_to_git(): checksafe becomes an integertboegi@web.de, Dec 29, 2017
  23. 1/1 Auto diff of UTF-16 files in UTF-8tboegi@web.de, Feb 26, 2018
  24. Peter KreftingFeb 26, 2018
  25. Jeff KingFeb 27, 2018
  26. Junio C HamanoDec 18, 2017
  27. Johannes SixtDec 18, 2017
  28. Jeff KingDec 15, 2017
  29. Lars SchneiderDec 18, 2017
  30. Jeff KingDec 18, 2017
  31. Torsten BögershausenDec 17, 2017
  32. Lars SchneiderDec 28, 2017
  33. Torsten BögershausenDec 29, 2017
  34. Lars SchneiderDec 29, 2017
  35. Junio C HamanoJan 3, 2018
  36. Lars SchneiderJan 3, 2018

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.