Differences of bundled Git/Mercurial to original ones
Asked by MikeL:

What are the exact details of the differences between the bundled Git/Mercurial versions compared to the original ones where they derived from?


Answers:
author: stevestreeting
body: Git is unchanged, it's just the binary version you can download from their site at the version number listed in the Preferences \> Git page.

Mercurial has had some minor patches applied to make sure things like password prompts are fully flushed even when called by something that's not a real terminal, so SourceTree can see them and respond. The full source code is included inside SourceTree (we tell you where in the About box, but for info it's SourceTree.app/Contents/Resources/mercurial_local) to comply with the GPL, and you can diff that against the source version of Mercurial to see the changes. Obviously if you diff it against the upstream source version at the version displayed in Preferences \> Mercurial you'll get just the changes we made.

That's what we do to comply with the GPL, but to make it even easier, here's the 2 patch files we apply to the embedded version. The first one isolates temporary files associated with checks to a location we can identify, so they don't make ST think that files have changed and cause an unnecessary refresh to occur

```
diff --git a/mercurial/dirstate.py b/mercurial_local/mercurial/dirstate.py--- a/mercurial/dirstate.py+++ b/mercurial/dirstate.py@@ -113,11 +113,25 @@      @propertycache     def _checklink(self):-        return util.checklink(self._root)+		 # Force checks to happen in '.hgcheck' folder so we can identify them+         d = os.path.join(self._root, '.hgcheck')+         try:+             if not os.path.isdir(d):+                 os.mkdir(d)+             return util.checklink(d)+         except (IOError, OSError):+             return False      @propertycache     def _checkexec(self):-        return util.checkexec(self._root)+		 # Force checks to happen in '.hgcheck' folder so we can identify them+         d = os.path.join(self._root, '.hgcheck')+         try:+             if not os.path.isdir(d):+                 os.mkdir(d)+             return util.checkexec(d)+         except (IOError, OSError):+             return False      @propertycache     def _checkcase(self):
```

The second deals with flushing user/password prompts:

```
--- a/mercurial-2.0/mercurial/ui.py	2011-11-01 20:36:00.000000000 +0000+++ b/mercurial/ui.py	2011-11-11 12:18:19.000000000 +0000@@ -551,19 +551,13 @@             except Exception:                 pass -        # call write() so output goes through subclassed implementation-        # e.g. color extension on Windows-        self.write(prompt)--        # instead of trying to emulate raw_input, swap (self.fin,-        # self.fout) with (sys.stdin, sys.stdout)-        oldin = sys.stdin-        oldout = sys.stdout-        sys.stdin = self.fin-        sys.stdout = self.fout-        line = raw_input(' ')-        sys.stdin = oldin-        sys.stdout = oldout+        # SourceTree mod: prompt using read_line instead which ensures prompt is flushed+        self.write_err(prompt)+        line = sys.stdin.readline()+        # get rid of \r+        line = line[:-1]+        #line = raw_input(prompt)+        # End SourceTree mod          # When stdin is in binary mode on Windows, it can cause         # raw_input() to emit an extra trailing carriage return@@ -604,7 +598,16 @@         if not self.interactive():             return default         try:-            return getpass.getpass(prompt or _('password: '))+            # Ensure we flush so that we can read prompt in non-terminal+            self.write_err('password:')+            pwd = sys.stdin.readline() +            # get rid of \r \n+            if pwd and pwd[-1] == '\n':+                pwd = pwd[:-1]+            if pwd and pwd[-1] == '\r':+                pwd = pwd[:-1]+                +            return pwd         except EOFError:             raise util.Abort(_('response expected'))     def status(self, *msg, **opts):
```

FWIW, I've tried to submit these patches to Mercurial upstream a few times but never managed to get them in, that's why we continue to patch Mercurial for our use.

comments: author: MikeL
body: Thanks Steve. When I download Git 1.7.11.1 from [http://git-scm.com/downloads](http://git-scm.com/downloads,), I only get a installer bundle. After install, /usr/local/git differs significantly from the bundled Git in Sourcetree (SourceTree.app/Contents/Resources/git_local). Do you have a different source of downloading Git?


author: MikeL
body: Steve, where do you get the original Git from?


author: MikeL
body: Steve, any update on this topic?


author: stevestreeting
body: Sorry for the late reply, I've been on vacation for a couple of weeks. My process for embedding git is literally this (from my own notes to remind me how to do it in fact :)

1. Download the official binary distribution and install
2. Copy the contents of the installed /usr/local/git folder into git_local
3. For size reasons, remove share/git-gui, share/gitk and share/gitweb, these are not needed

Therefore I can't understand how you'd conclude the binary download is different, except maybe for the things I trimmed out to make the embedded version a little smaller. I used to have a step which stripped the 'ppc' or 'ppc7400' elements from the fat binaries, because the git binary distro used to include PowerPC support as well as i386 and Apple don't let you distribute that any more, but I haven't had to do that for a while because Git stopped packaging ppc support a year or so ago.


author: MikeL
body: Thanks for the update. From where do you download the official Git binaries?


author: stevestreeting
body: Always from [git-scm.com](http://git-scm.com), which is why I'm confused. I don't even dig any further than the front page, just grab the latest binary from the front page link when periodically updating the embedded version.


author: MikeL
body: Could the differences be caused by the digital signature of SourceTree? If so, how to remove this signature for testing purposes?


author: stevestreeting
body: Ah, that's very likely - we were required to sign every binary inside the .app to comply with both the App Store and the GateKeeper requirements on 10.7+ otherwise OS X wouldn't consider them valid. I'm not sure how you remove a code signature - we used the usual 'codesign' tool but I can't see an option to strip the signature back off again. It must be possible though, since nothing is recompiled when you sign the code, it just tacks on a signature that OS X can check.