0

Disclaimer: This question exists because of Unity3D and its library issue.

I've tried getting current git-cache-meta.sh and use it on windows. It doesn't work.

The first error I got was on this line:

$ find `git ls-files`
find: invalid predicate `-'

Changing it to the original find $(git ls-files) also doesn't work (i.e. both syntaxes are no good).

The invalid predicate is certainly due to a file named such as "boo - foo.bar". And so I tried to run find "$(git ls-files)". Then it turned into a very ugly error/bug.

I wish to know why command substitution (the weird $() doesn't work on mingw, but, more importantly:

How can we make git-cache-meta.sh work properly on mingw?

As you can see below, I actually manage to answer this without that keyword -> properly. So I still hope someone might come up with a fast and clean solution <- reason why I'm using this script to begin with.

Community
  • 1
  • 1
cregox
  • 17,674
  • 15
  • 85
  • 116

3 Answers3

1

I found a big and convoluted, thus hard to port, and slow solution. Too slow. Waaaay too slow. Takes over a minute to go through my git, which have about 9k files. But, none the less, here it is, thanks to Dave Taylor, google and many man pages. Basically, use for and Dave's hack instead of find:

git ls-files -d > .temp_gitcachemeta
for s in $(git ls-files | grep -vf .temp_gitcachemeta | sed 's/ /_+_/g');
    do t="$(echo $s | sed s'/_+_/ /g')";
    echo "touch -c -m -d \"$(date -r "$t" +'%F %T')\" \"$t\"";
done
rm .temp_gitcachemeta ;;

Using temp file here because it seems like mingw also doesn't support process substitution.

cregox
  • 17,674
  • 15
  • 85
  • 116
1

The original script was written in an elegant and complex style (probably more so than necessary). I rewrote it with most of the complexity removed. I don't know which feature is breaking on mingw, but this is more likely to work:

GIT_CACHE_META_FILE=.git_cache_meta
case $@ in
    --store)
        git ls-files|while read file; do
            find "$file" \( -printf 'chown %U %p\n' \) \
               \( -printf 'chgrp %G %p\n' \) \
               \( -printf 'chmod %#m %p\n' \) \
               \( -printf 'touch -c -d -m "%TY-%Tm-%Td %TH:%TM:%TS" "%p"\n' \)
        done | tee $GIT_CACHE_META_FILE
        ;;
    --apply)
        sh -e $GIT_CACHE_META_FILE
        ;;
    *)
        echo "Usage: $0 --store|--apply"; exit 1
        ;;
esac

The only thing that's likely to go wrong is if one of the executables on your system doesn't support all the options than are used here. That would be: find, chown, chgrp, touch, and chmod.

cregox
  • 17,674
  • 15
  • 85
  • 116
piojo
  • 6,351
  • 1
  • 26
  • 36
  • This is **freaking awesome**!! I still get a weird error which makes it stop in the middle of the whole thing, but this is exactly what I've asked and it's much better to work on this than the original! Thanks. – cregox Jul 26 '13 at 11:42
  • While I'm on it, I would change few things: (1) remove the `tee` and use straight [redirection](http://linuxcommand.org/lts0060.php) `>` if that's faster (or add a `> /dev/null` if it isn't). (2) remove `find` and use anything else. `find` is the whole culprit in `MinGW`, very defective implementation. As I've mentioned above, it crashes on my case with a stack dumped `STATUS_ACCESS_VIOLATION`. So, for instance, the line for `touch` could be this instead: `echo "touch -c -d -m \"$(date -r "$file" +'%F %T')\" \"$file\"";` (as I did in my answer). Again, thank you so much, piojo! – cregox Jul 26 '13 at 12:32
  • Glad I helped a little. I couldn't remove the "find" usage because I didn't know how else to get all the metadata that's being requested in that line, and I didn't actually know which metadata was necessary. – piojo Aug 01 '13 at 03:02
  • Note that if you want to use this for Unity game data and want to avoid undefined Unity state, you should only restore the old metadata if the file content is the same as it was. Unity needs to see that updated timestamp if a file content is different since it was imported. This means if you need to use a very old checkout (everything has changed), there's no helping the long reimport time. – piojo Aug 01 '13 at 03:03
  • I wish it were that simple... From my tests, Unity doesn't use only timestamps to rebuild the library after all. – cregox Aug 01 '13 at 10:50
  • Wow, thanks, first solution that works. It's slow, though. I also prefer solutions that would change timestamp to the last commit timestamp, and not require to be run twice nor a place to save metadata. – Rolf Dec 30 '13 at 15:49
0

MinGW likes to call native Windows tools which add a Carriage Return (CR, \r) to the end of each line. So you can replace $(commandname) with $(commandname | sed $'s/\r$//') or something similar.

Another option is to try something more Unix-y, such as Interix/SFU/SUA or Cygwin or MSYS or AT&T UWIN.

As for metadata in general, your problem will be that things like chown, chgrp, chmod and touch will behave differently on the Windows® platform, and some things will not even exist, especially on FAT filesystems, whereas NTFS has a completely different set of metadata (different format for time stamps, ACLs instead of Unix user/group/other permissions, etc.) so it’s likely to require some development work from someone who understands the Unix scripting world and the NT platform well.

Finally, I’d like to say that this script is a security hole since it just evaluates stored commands, so if anyone else has got the ability to write to the .git_cache_meta file, they will own your system.

cregox
  • 17,674
  • 15
  • 85
  • 116
mirabilos
  • 5,123
  • 2
  • 46
  • 72
  • (1) Awesome idea on the CR! but using `| sed $'s/\r$//'` didn't work. (2) I'm using `mingw` because that's what comes with `git`, so I really don't want to use anything else (since I'm trying to make a git hook). (3) `touch` seem to be working fine. I don't really care for the rest, but they also seem to work without issues. (4) Damn, I wouldn't even think about this kind of hole... In any case, if someone malicious have access to that file, he already found a much worse hole elsewhere. (finally) So far, I couldn't make any use of this answer. :( But thanks. – cregox Jul 24 '13 at 16:29
  • Also, I've just tried the theory (1) and did `git ls-files > textfile`. No matter how I do it, the textfile never brings any CR. It's only LF (or "0a", or ASCII 10). So that probably isn't the issue. Plus, the error does point to a **`"-"`**, so I'm guessing *MinGW* is not properly interpreting file names which contain an hyphen under the command substitution, for whatever reason (bug). – cregox Jul 24 '13 at 16:59
  • 1
    OK. Sorry then, but apparently this wasn’t the issue at hand. (I’ve seen it being the problem, that’s why I suggested it.) Good luck! – mirabilos Jul 26 '13 at 13:46