def clear(self): if os.path.exists('test_diff_command_git_repo_dir'): try: RmTree('test_diff_command_git_repo_dir') except: time.sleep(1) RmTree('test_diff_command_git_repo_dir')
def testActionDiff(self): temp_dir = 'test_diff_command_git_repo_dir' git = r'C:\D\bin\git\bin\git.exe' if not os.path.exists(git): git = 'git' self.git = git # Test diffing with new folder structure subprocess.call([git] + 'init test_diff_command_git_repo_dir'.split(), cwd='.') os.mkdir(os.path.join(temp_dir, 'folder1')) with open(os.path.join(temp_dir, 'folder1', 'out.txt'), 'w') as f: f.write('out') called = self.CallDiff() self.assertEqual(['winmergeu.exe'], called) # Test diffing with previous version of HEAD without changes subprocess.call([git] + 'add -A'.split(), cwd=temp_dir) subprocess.call([git] + 'commit -m "Second'.split(), cwd=temp_dir) called = self.CallDiff() self.assertEqual([], called) #Not called as we don't have any changes. # Test diffing with previous version of HEAD^ def CheckStructure(): prev = os.path.join('.mu.diff.git.tmp', 'REPO', 'test_diff_command_git_repo_dir', 'folder1', 'out.txt') curr = os.path.join('.mu.diff.git.tmp', 'WORKING', 'test_diff_command_git_repo_dir', 'folder1', 'out.txt') self.assert_(os.path.exists(prev)) self.assert_(os.path.exists(curr)) Print('prev', open(prev, 'r').read()) Print('curr', open(curr, 'r').read()) with open(os.path.join(temp_dir, 'folder1', 'out.txt'), 'w') as f: f.write('new out') subprocess.call([git] + 'add -A'.split(), cwd=temp_dir) subprocess.call([git] + 'commit -m "Second'.split(), cwd=temp_dir) called = self.CallDiff('HEAD^', check_structure=CheckStructure) self.assertEqual(['winmergeu.exe'], called) # Test diffing dir structure in git changed for file in working dir subprocess.call([git] + 'add -A'.split(), cwd=temp_dir) subprocess.call([git] + 'commit -m "Third'.split(), cwd=temp_dir) RmTree(os.path.join(temp_dir, 'folder1')) with open(os.path.join(temp_dir, 'folder1'), 'w') as f: f.write('folder1 is now file.') called = self.CallDiff() self.assertEqual(['winmergeu.exe'], called) # Do mu st/mu up just to check if it works. from mu_repo.action_default import Run config = Config(repos=[temp_dir], git=git) Run(Params(config, ['st'], config_file=None)) import mu_repo mu_repo.main(config_file=None, args=['up'])
def symlink(src, target): if os.path.isdir(src): if os.path.exists(target): os.rmdir(target) shutil.copytree(src, target) keep_files_synched.KeepInSync(src, target) else: if os.path.exists(target): if os.path.isdir(target): RmTree(target) else: os.remove(target) shutil.copyfile(src, target) keep_files_synched.KeepInSync(src, target)
def clear(self): if os.path.exists('test_temp_dir'): RmTree('test_temp_dir')
def test_action_diff(): temp_dir = 'test_diff_command_git_repo_dir' # Test diffing with new folder structure subprocess.call([git, 'init', temp_dir], cwd='.') configure_git_user(cwd=temp_dir) os.mkdir(os.path.join(temp_dir, 'folder1')) with open(os.path.join(temp_dir, 'folder1', 'out.txt'), 'w') as f: f.write('out') called = _call_diff() if sys.platform.startswith('win'): merge_command = 'winmergeu.exe' else: merge_command = 'meld' assert [merge_command] == called # Test diffing with previous version of HEAD without changes subprocess.check_call([git] + 'add -A'.split(), cwd=temp_dir) subprocess.check_call([git] + 'commit -m "Second'.split(), cwd=temp_dir) called = _call_diff() assert [] == called # Not called as we don't have any changes. # Test diffing with previous version of HEAD~1 def check_structure(): prev = os.path.join('.mu.diff.git.tmp', 'REPO', 'test_diff_command_git_repo_dir', 'folder1', 'out.txt') curr = os.path.join('.mu.diff.git.tmp', 'WORKING', 'test_diff_command_git_repo_dir', 'folder1', 'out.txt') assert os.path.exists(prev) assert os.path.exists(curr) Print('prev', open(prev, 'r').read()) Print('curr', open(curr, 'r').read()) with open(os.path.join(temp_dir, 'folder1', 'out.txt'), 'w') as f: f.write('new out') subprocess.check_call([git] + 'add -A'.split(), cwd=temp_dir) subprocess.check_call([git] + 'commit -m "Second'.split(), cwd=temp_dir) called = _call_diff('HEAD~1', check_structure=check_structure) assert [merge_command] == called # Test diffing dir structure in git changed for file in working dir # Nothing changed at this point: newest git now gives a non-zero value in # such a case if we try to commit. # subprocess.check_call([git] + 'add -A'.split(), cwd=temp_dir) # subprocess.check_call([git] + 'commit -m "Third'.split(), cwd=temp_dir) RmTree(os.path.join(temp_dir, 'folder1')) with open(os.path.join(temp_dir, 'folder1'), 'w') as f: f.write('folder1 is now file.') called = _call_diff() assert [merge_command] == called # Do mu st/mu up just to check if it works. from mu_repo.action_default import Run config = Config(repos=[temp_dir], git=git) Run(Params(config, ['st'], config_file=None)) import mu_repo mu_repo.main(config_file=None, args=['up'])
def Run(params): config = params.config join = os.path.join temp_dir_name = '.mu.diff.git.tmp' if os.path.exists(temp_dir_name): n = '' while n not in ('y', 'n'): n = raw_input( 'Temporary dir for diff: %s already exists. Delete and continue (y) or cancel (n)? ' % (temp_dir_name, )).strip().lower() if n == 'y': RmTree(temp_dir_name) break if n == 'n': Print('Canceling diff action.') return temp_working = join(temp_dir_name, 'WORKING') temp_repo = join(temp_dir_name, 'REPO') os.mkdir(temp_dir_name) os.mkdir(temp_working) os.mkdir(temp_repo) from mu_repo import keep_files_synched def symlink(src, target): if os.path.isdir(src): if os.path.exists(target): os.rmdir(target) shutil.copytree(src, target) keep_files_synched.KeepInSync(src, target) else: if os.path.exists(target): if os.path.isdir(target): RmTree(target) else: os.remove(target) shutil.copyfile(src, target) keep_files_synched.KeepInSync(src, target) try: #Note: we could use diff status --porcelain instead if we wanted to check untracked files. #cmd = [git] + 'diff --name-only -z'.split() args = params.args branch = '' repos_and_curr_branch = None if len(args) > 1: #Ok, the user is comparing current branch with a previous branch or commit. #i.e.: mu dd HEAD^^ branch = args[1] if branch == '--prev': repos_and_curr_branch = dict( GetReposAndCurrBranch(params, verbose=False)) threads = [] for repo in config.repos: if repos_and_curr_branch is not None: #Note: if --prev is given, it means current_branch@{1} #But note that users could also do things as: mu dd master@{10.minutes.ago} #References: #http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html #http://stackoverflow.com/questions/1362952/detail-change-after-git-pull branch = repos_and_curr_branch[ repo] + '@{1}' #Get the version before the last update. thread = DoDiffOnRepoThread(config, repo, symlink, temp_working, temp_repo, branch) else: thread = DoDiffOnRepoThread(config, repo, symlink, temp_working, temp_repo, branch) threads.append(thread) thread.start() for thread in threads: thread.join() thread_pool.Join() for thread in threads: if thread.entry_count != 0: break else: Print('No changes found.') return if sys.platform == 'win32': write_left = ['/wl'] #Cannot write on left if not branch: write_left = [ ] #Can write on left when not working with branch (i.e.: working dir). winmerge_cmd = 'WinMergeU.exe /r /u /wr /dl WORKINGCOPY /dr HEAD'.split( ) cmd = winmerge_cmd + write_left + [temp_working, temp_repo] try: subprocess.call(cmd) except: Print('Error calling: %s' % (' '.join(cmd), )) else: # Winmerge is not available on Linux, so, let's use another option (meld) cmd = ['meld', temp_working, temp_repo] try: subprocess.call(cmd) except: Print('Error calling: %s' % (' '.join(cmd), )) finally: #If we've gone to the synching mode, make sure we had a last synchronization before #getting out of the diff. if keep_files_synched is not None: keep_files_synched.StopSyncs() def onerror(*args): Print('Error removing temporary directory structure: %s' % (args, )) RmTree(temp_dir_name, onerror=onerror)
def Run(params): config = params.config join = os.path.join temp_dir_name = '.mu.diff.git.tmp' if os.path.exists(temp_dir_name): n = '' while n not in ('y', 'n'): n = raw_input( 'Temporary dir for diff: %s already exists. Delete and continue (y) or cancel (n)? ' % (temp_dir_name, )).strip().lower() if n == 'y': RmTree(temp_dir_name) break if n == 'n': Print('Canceling diff action.') return temp_working = join(temp_dir_name, 'WORKING') temp_repo = join(temp_dir_name, 'REPO') os.mkdir(temp_dir_name) os.mkdir(temp_working) os.mkdir(temp_repo) #=============================================================================================== # Define symlink utility #=============================================================================================== keep_files_synched = None try: if not hasattr(os, 'symlink'): import win32file #Note: not all users can do it... #http://stackoverflow.com/questions/2094663/determine-if-windows-process-has-privilege-to-create-symbolic-link #see: http://bugs.python.org/issue1578269 #see: http://technet.microsoft.com/en-us/library/cc766301%28WS.10%29.aspx def symlink(src, target): win32file.CreateSymbolicLink(src, target, 1) else: symlink = os.symlink #Just check if it does indeed work... if it doesn't redefine and use our polling strategy. symlink(temp_working, join(temp_dir_name, 'lnk_test')) except: from mu_repo import keep_files_synched def symlink(src, target): if os.path.isdir(src): if os.path.exists(target): os.rmdir(target) shutil.copytree(src, target) keep_files_synched.KeepInSync(src, target) else: if os.path.exists(target): if os.path.isdir(target): RmTree(target) else: os.remove(target) shutil.copyfile(src, target) keep_files_synched.KeepInSync(src, target) try: #Note: we could use diff status --porcelain instead if we wanted to check untracked files. #cmd = [git] + 'diff --name-only -z'.split() args = params.args branch = '' repos_and_curr_branch = None if len(args) > 1: #Ok, the user is comparing current branch with a previous branch or commit. #i.e.: mu dd HEAD^^ branch = args[1] if branch == '--prev': repos_and_curr_branch = dict( GetReposAndCurrBranch(params, verbose=False)) threads = [] for repo in config.repos: if repos_and_curr_branch is not None: #Note: if --prev is given, it means current_branch@{1} #But note that users could also do things as: mu dd master@{10.minutes.ago} #References: #http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html #http://stackoverflow.com/questions/1362952/detail-change-after-git-pull branch = repos_and_curr_branch[ repo] + '@{1}' #Get the version before the last update. thread = DoDiffOnRepoThread(config, repo, symlink, temp_working, temp_repo, branch) else: thread = DoDiffOnRepoThread(config, repo, symlink, temp_working, temp_repo, branch) threads.append(thread) thread.start() for thread in threads: thread.join() thread_pool.Join() for thread in threads: if thread.entry_count != 0: break else: Print('No changes found.') return write_left = ['/wl'] #Cannot write on left if not branch: write_left = [ ] #Can write on left when not working with branch (i.e.: working dir). winmerge_cmd = 'WinMergeU.exe /r /u /wr /dl WORKINGCOPY /dr HEAD'.split( ) cmd = winmerge_cmd + write_left + [temp_working, temp_repo] try: subprocess.call(cmd) except: Print('Error calling: %s' % (' '.join(cmd), )) finally: #If we've gone to the synching mode, make sure we had a last synchronization before #getting out of the diff. if keep_files_synched is not None: keep_files_synched.StopSyncs() def onerror(*args): Print('Error removing temporary directory structure: %s' % (args, )) RmTree(temp_dir_name, onerror=onerror)