Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import sys, os, popen2
+import sys, os, popen2, re, gitmergeonefile
from stgit.utils import *
# Functions
#
+# GIT_DIR value cached
+__base_dir = None
+
def get_base_dir():
"""Different start-up variables read from the environment
"""
- if 'GIT_DIR' in os.environ:
- return os.environ['GIT_DIR']
- else:
- return _output_one_line('git-rev-parse --git-dir')
+ global __base_dir
+
+ if not __base_dir:
+ if 'GIT_DIR' in os.environ:
+ __base_dir = os.environ['GIT_DIR']
+ else:
+ __base_dir = _output_one_line('git-rev-parse --git-dir')
+
+ return __base_dir
def get_commit(id_hash):
"""Commit objects factory. Save/look-up them in the __commits
return commit_id
-def apply_diff(rev1, rev2):
+def apply_diff(rev1, rev2, check_index = True):
"""Apply the diff between rev1 and rev2 onto the current
index. This function doesn't need to raise an exception since it
is only used for fast-pushing a patch. If this operation fails,
the pushing would fall back to the three-way merge.
"""
- return os.system('git-diff-tree -p %s %s | git-apply --index 2> /dev/null'
- % (rev1, rev2)) == 0
+ if check_index:
+ index_opt = '--index'
+ else:
+ index_opt = ''
+ cmd = 'git-diff-tree -p %s %s | git-apply %s 2> /dev/null' \
+ % (rev1, rev2, index_opt)
+
+ return os.system(cmd) == 0
def merge(base, head1, head2):
"""Perform a 3-way merge between base, head1 and head2 into the
local tree
"""
refresh_index()
- if __run('git-read-tree -u -m', [base, head1, head2]) != 0:
+ if __run('git-read-tree -u -m --aggressive', [base, head1, head2]) != 0:
raise GitException, 'git-read-tree failed (local changes maybe?)'
- # this can fail if there are conflicts
- if __run('git-merge-index -o -q gitmergeonefile.py -a') != 0:
- raise GitException, 'git-merge-index failed (possible conflicts)'
+ # check the index for unmerged entries
+ files = {}
+ stages_re = re.compile('^([0-7]+) ([0-9a-f]{40}) ([1-3])\t(.*)$', re.S)
+
+ for line in _output('git-ls-files --unmerged --stage -z').split('\0'):
+ if not line:
+ continue
+
+ mode, hash, stage, path = stages_re.findall(line)[0]
+
+ if not path in files:
+ files[path] = {}
+ files[path]['1'] = ('', '')
+ files[path]['2'] = ('', '')
+ files[path]['3'] = ('', '')
+
+ files[path][stage] = (mode, hash)
+
+ # merge the unmerged files
+ errors = False
+ for path in files:
+ stages = files[path]
+ if gitmergeonefile.merge(stages['1'][1], stages['2'][1],
+ stages['3'][1], path, stages['1'][0],
+ stages['2'][0], stages['3'][0]) != 0:
+ errors = True
+
+ if errors:
+ raise GitException, 'GIT index merging failed (possible conflicts)'
def status(files = None, modified = False, new = False, deleted = False,
conflict = False, unknown = False, noexclude = False):