def execute(self, options, quiet=False, **kwargs): if not options.branch: self.message = 'ERROR: Could not determine branch.' return False working_dir = os.getcwd() root = find_hg_root() if root: os.chdir(root) os.chdir("..") if not os.path.exists('.hg'): os.chdir(working_dir) self.message = 'ERROR: Must be in root of working copy to use the switch command.' return False if len(options.args) == 0: os.chdir(working_dir) self.message = 'ERROR: A target branch name must be specified.' return False self.mb_root = find_mb_root() # this will not return if we can't find a working location self.mb_switch = os.path.join(self.mb_root, 'switch') if not os.path.exists(self.mb_switch): try: os.mkdir(self.mb_switch) except: self.message = 'ERROR: Could not create folder "%s".' % self.mb_switch return False target_branch = options.args[0] # validate the target branch name output = subprocess.Popen(['hg', 'branches'], stdout=subprocess.PIPE).communicate()[0].decode("utf-8") found = False for line in output.split('\n'): data = re.search('([a-zA-Z0-9\.]+)\s+', line) if not data: continue if target_branch == data.group(1): found = True break if not found: os.chdir(working_dir) self.message = 'ERROR: The specified target branch "%s" cannot be validated.' % target_branch return False # are there any pending changes? output = subprocess.Popen(['hg', 'status', '--quiet'], stdout=subprocess.PIPE).communicate()[0].decode("utf-8") if len(output): # shelve the changes if not self.shelve(options): os.chdir(working_dir) return False # now the easy part... if subprocess.call(['hg', 'update', target_branch]) != 0: self.message = 'ERROR: Switching to the target branch "%s" failed.' % target_branch # ok, restore the shelved work above, if any if not self.restore(options): # whoa..everything's going to Hell in a handbasket... self.message = '%s\nERROR: Failed to restore the shelved microbranch for current branch "%s".' % options.branch return False # apply any cached micro-branch work options.args[0] = target_branch # make sure we overwrite things options.overwrite = True if not self.restore(options): print(self.message, file=sys.stderr) self.message = 'ERROR: Failed to apply cached micro-branch to branch "%s".' % target_branch return False # if restore() is successful, any cached data for the target # branch is deleted # we're done! os.chdir(working_dir) return True
def __init__(self, options): if not options.branch: return working_dir = os.getcwd() root = find_hg_root() if root: # set working directory to the top of the working copy os.chdir(root) os.chdir("..") if not os.path.exists('.hg'): os.chdir(working_dir) print("ERROR: Must be in root of working copy to shelf.", file=sys.stderr) sys.exit(1) shelf_name = 'shelf' if len(options.shelf_name): shelf_name = options.shelf_name shelf_name_unquoted = shelf_name shelf_name = quote(shelf_name, '') root = find_mb_root( ) # this will not return if we can't find a working location manifest_version = 0 manifest = [] manifest_name = os.path.join(root, '%s.manifest' % shelf_name) manifest_archive = os.path.join(root, '%s.7z' % shelf_name) manifest_comment = '' if not os.path.exists(manifest_name): if shelf_name == 'shelf': print('Working copy has no cached default microbranch.') else: print('Cannot access microbranch "%s".' % shelf_name_unquoted) else: manifest_version = 0 manifest_lines = open(manifest_name).readlines() if manifest_lines[0].startswith('version '): manifest_version = int(manifest_lines[0][8:]) del manifest_lines[0] if manifest_version >= 1: manifest_comment = manifest_lines[1].rstrip() del manifest_lines[0] else: manifest_comment = manifest_lines[0].rstrip() del manifest_lines[0] conflict_count = 0 for line in manifest_lines: line = line.rstrip() if len(line) == 0: continue status, file_name, previous_key = line.split( '?' ) # 'previous_key' will be an md5 hash starting with MANIFEST_VERSION 2 if status == 'M': if os.name == 'nt': file_name = file_name.replace('/', '\\') else: file_name = file_name.replace('\\', '/') files_are_equal = False # see if the file is unchanged by the merge; in that case, just copy it if manifest_version <= 1: new_key = get_changeset_for(options, file_name) if not new_key: print( "ERROR: Failed to determine changeset for file '%s'!" % file_name, file=sys.stderr) os.chdir(working_dir) sys.exit(1) old_crc32 = crc32( os.path.join(working_folder, file_name)) new_crc32 = crc32(file_name) files_are_equal = (previous_key == new_key) and (old_crc32 == new_crc32) else: new_key = hashlib.md5(open(file_name, 'rb').read()).hexdigest() files_are_equal = new_key == previous_key if not files_are_equal: if conflict_count == 0: print( 'Intervening differences detected for the following "%s" microbranch assets:' % (shelf_name_unquoted if shelf_name_unquoted != "shelf" else "default")) print('\t', file_name) conflict_count += 1 if conflict_count == 0: print( 'No intervening differences detected for "%s" microbranch.' % (shelf_name_unquoted if shelf_name_unquoted != "shelf" else "default")) os.chdir(working_dir)
def execute(self, options, quiet=False, **kwargs): if not options.branch: self.message = 'ERROR: Could not determine branch.' return False working_dir = os.getcwd() root = find_hg_root() if root: os.chdir(root) os.chdir("..") stage_path = StageIO().get_staging_root(root, options) if os.path.exists(stage_path): stages = os.listdir(stage_path) stage_path = os.path.join(".hg", "stage") if len(stages) != 0 else None else: stage_path = None if not os.path.exists('.hg'): os.chdir(working_dir) self.message = 'ERROR: Must be in root of working copy to shelf.' return False command = ['hg', 'status', '-q', '-C'] if (options.include_filter is None) and (len(options.exclude_filter) == 0): command.append(options.use_path) output = subprocess.Popen( command, stdout=subprocess.PIPE).communicate()[0].decode("utf-8") if len(output) > 0: lines = fixup_renames(output.split('\n')) shelf_name = 'shelf' if len(options.shelf_name) != 0: shelf_name = options.shelf_name shelf_name_unquoted = shelf_name shelf_name = quote(shelf_name, '') if 'mb_root' in kwargs: root = kwargs['mb_root'] else: root = find_mb_root( ) # this will not return if we can't find a working location manifest_version = 0 manifest = [] manifest_name = os.path.join(root, '%s.manifest' % shelf_name) manifest_archive = os.path.join(root, '%s.7z' % shelf_name) manifest_comment = '' timestamp = hex(int(time.time()))[2:] if os.path.exists(manifest_name): # grab the previous comment manifest_lines = open(manifest_name).readlines() if manifest_lines[0].startswith('version '): manifest_version = int(manifest_lines[0][8:]) if manifest_version >= 1: manifest_comment = manifest_lines[1].rstrip() else: manifest_comment = manifest_lines[0].rstrip() manifest_lines = None try: os.rename(manifest_name, '%s.%s' % (manifest_name, timestamp)) except: os.chdir(working_dir) self.message = 'ERROR: Could not back up previous shelf.' return False if os.path.exists(manifest_archive): try: os.rename(manifest_archive, '%s.%s' % (manifest_archive, timestamp)) except: os.chdir(working_dir) self.message = 'ERROR: Could not back up previous shelf.' return False if len(options.comment): manifest_comment = options.comment shelve_command = [ options.seven_zip, 'a', manifest_archive, '@%s.list' % shelf_name ] for line in lines: line = line.strip() if not len(line): continue if (options.include_filter is not None) or len( options.exclude_filter): if options.include_filter is not None: if options.include_filter in line: manifest.append(line) if len(options.exclude_filter): exclude = [ f for f in options.exclude_filter if f in line ] if len(exclude) == 0: manifest.append(line) else: manifest.append(line) if options.ide_state: # find all the .suo files and add them to the archive # (the Visual Studio .suo file maintains a record of all files that # were last open in the IDE) if os.path.exists('.vs'): # VS2017+ for root, dirs, files in os.walk('.vs'): if '.suo' in files: manifest.append('X %s' % os.path.join(root, '.suo')) options.extra_files.append( os.path.join(root, '.suo')) else: # +VS2013 files = glob.glob('*.suo') if len(files): options.extra_files += files for file in files: manifest.append('X %s' % file) lines_written = 0 with open('%s.list' % shelf_name, 'w') as f: if stage_path is not None: f.write('%s\n' % stage_path) # capture current staging metadata if isinstance(options.extra_files, (list, tuple)) and len(options.extra_files): # should be a path relative to the root of the working copy f.write('%s\n' % '\n'.join(options.extra_files)) for line in manifest: action = line[0] if action == 'M' or action == 'A': f.write('%s\n' % line[2:]) lines_written += 1 if action == 'V': # rename; place the current file into the backup in case it holds changes f.write('%s\n' % line[2:].split(',')[1]) lines_written += 1 if lines_written: output = subprocess.Popen( shelve_command, stdout=subprocess.PIPE).communicate()[0].decode("utf-8") lines = output.split('\n') something_went_wrong = True for line in lines: line = line.rstrip() if line == 'Everything is Ok': something_went_wrong = False break if something_went_wrong: os.chdir(working_dir) self.message = 'ERROR: Failed to construct shelf archive:\n%s' % output return False os.remove('%s.list' % shelf_name) if (options.include_filter is not None) or len( options.exclude_filter): for line in manifest: action = line[0] filename = line[2:] if action == 'V': filename = line[2:].split(',')[1] command = ['hg', 'revert', filename] output = subprocess.Popen( command, stdout=subprocess.PIPE).communicate()[0].decode( "utf-8") elif not options.no_revert: command = ['hg', 'revert', '--all'] if options.use_path != '.': command.append(options.use_path) output = subprocess.Popen( command, stdout=subprocess.PIPE).communicate()[0].decode("utf-8") if stage_path is not None: shutil.rmtree( stage_path) # remove current staging metadata with open(manifest_name, 'w') as f: f.write('version %d\n' % MANIFEST_VERSION) f.write('%s\n' % manifest_comment) for line in manifest: action = line[0] if os.name == 'nt': file_name = line[2:].replace('/', '\\') else: file_name = line[2:].replace('\\', '/') #timestamp = 0.0 changeset = '' if action == 'M': changeset = hashlib.md5(open(file_name, 'rb').read()).hexdigest() elif action == 'V': # the revert above may have left the renamed file in place # we are nice, and clean it up for them... from_name, to_name = file_name.split(',') if os.path.exists(to_name): try: os.remove(to_name) except: self.message = 'ERROR: Failed to remove renamed file "%s"!' % to_name return False changeset = hashlib.md5(open(from_name, 'rb').read()).hexdigest() f.write('%s?%s?%s\n' % (action, file_name, changeset)) batch_text = '' if os.name == 'nt': batch_text = '@echo off\n' batch_text += 'set FG=%_fg\n' batch_text += 'set BG=%_bg\n' manifest = colorize_status(manifest) if not quiet: print('Shelved the following state as microbranch "%s":' % shelf_name_unquoted) for line in manifest: if options.ansi_color: if options.ansi_color_requires_batch: batch_text += 'echo %s\n' % line[3] else: print(line[3]) else: print(line[0], line[1]) if options.ansi_color: if options.ansi_color_requires_batch: if os.name == 'nt': batch_text += 'color %FG on %BG\n' open(options.batch_file_name, 'w').write(batch_text) os.system(options.batch_file_name) if options.no_revert: print( '\nAs requested, changes have been left in the working copy.' ) else: if not quiet: print('Nothing to shelve.') os.chdir(working_dir) return True
def execute(self, options, quiet=False, **kwargs): abort_cleanups = [] def abort_cleanup(cleanups): for cleanup in cleanups: cleanup() if not options.branch: self.message = 'ERROR: Could not determine branch.' return False shelf_name = 'shelf' if len(options.shelf_name) != 0: shelf_name = options.shelf_name shelf_name_unquoted = shelf_name shelf_name = quote(shelf_name, '') working_dir = os.getcwd() root = find_hg_root() if root: os.chdir(root) os.chdir("..") if not os.path.exists('.hg'): os.chdir(working_dir) self.message = 'ERROR: Must be in root of working copy to restore.' return False if 'mb_root' in kwargs: self.mb_root = kwargs['mb_root'] else: self.mb_root = find_mb_root( ) # this will not return if we can't find a working location if not os.path.exists( os.path.join(self.mb_root, '%s.manifest' % shelf_name)): os.chdir(working_dir) self.message = 'ERROR: A valid shelf state could not be found.' return False command = ['hg', 'status', '-q', '.'] output = subprocess.Popen( command, stdout=subprocess.PIPE).communicate()[0].decode("utf-8") if len(output) != 0: os.chdir(working_dir) self.message = 'Cannot restore into pending changes.' return False working_folder = os.path.join(tempfile.gettempdir(), '__%s__' % shelf_name) if os.path.exists(working_folder): try: shutil.rmtree(working_folder) except: os.chdir(working_dir) self.message = 'ERROR: Failed to remove remnants of previous restore atttempt.' return False manifest_name = os.path.join(self.mb_root, '%s.manifest' % shelf_name) manifest_archive = os.path.join(self.mb_root, '%s.7z' % shelf_name) if not os.path.exists(manifest_archive): os.chdir(working_dir) self.message = 'ERROR: The specified microbranch "%s" does not exist.' % shelf_name return False restore_command = [ options.seven_zip, 'x', '-o%s' % working_folder, manifest_archive ] output = subprocess.Popen( restore_command, stdout=subprocess.PIPE).communicate()[0].decode("utf-8") lines = output.split('\n') something_went_wrong = True for line in lines: line = line.rstrip() if line == 'Everything is Ok': something_went_wrong = False break if something_went_wrong: os.chdir(working_dir) self.message = 'ERROR: Failed to extract shelf archive:\n%s' % output return False # does this archive contain any staging areas? it won't be in the # archive unless it has staging areas shelved_stage = os.path.join(working_folder, '.hg', 'stage') stage_path = StageIO().get_staging_root(root, options) if os.path.exists(shelved_stage): # ok, check to make sure there isn't one lingering if os.path.exists(stage_path): stage_areas = os.listdir(stage_path) if len(stage_areas) != 0: # we have to abort; cleanup() will remove the working_folder os.chdir(working_dir) self.message = 'ERROR: Active staging areas found; cannot overwrite with shelved version' return False shutil.rmtree(stage_path) shutil.copytree(shelved_stage, stage_path) abort_cleanups.append(lambda: shutil.rmtree(stage_path)) else: shelved_stage = None manifest_version = 0 manifest_lines = open(manifest_name).readlines() if manifest_lines[0].startswith('version '): manifest_version = int(manifest_lines[0][8:]) del manifest_lines[0] if manifest_version >= 1: manifest_comment = manifest_lines[1].rstrip() del manifest_lines[0] else: manifest_comment = manifest_lines[0].rstrip() del manifest_lines[0] abort_cleanups.append( lambda: subprocess.check_output(['hg', 'revert', '--all'])) abort_cleanups.append(lambda: os.chdir(working_dir)) merge_status = {} add_status = {} for line in manifest_lines: line = line.rstrip() status, file_name, previous_key = line.split( '?' ) # 'previous_key' will be an md5 hash starting with MANIFEST_VERSION 2 if os.name == 'nt': file_name = file_name.replace('/', '\\') else: file_name = file_name.replace('\\', '/') if status == 'A': if os.path.exists(file_name): output = subprocess.Popen( ['hg', 'add', file_name], stdout=subprocess.PIPE).communicate()[0].decode( "utf-8") if not len(output): add_status[file_name] = True if not quiet: print('.', end='') else: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore added file "%s":\n%s\n...aborting restore...' % ( file_name, output) return False else: if not os.path.exists( os.path.join(working_folder, file_name)): add_status[file_name] = False if not quiet: print( "WARNING: Added file '%s' no longer exists; skipping..." % file_name, file=sys.stderr) else: if not make_path(file_name): abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to recreate path for added file "%s"; aborting restore...' % file_name return False try: shutil.copyfile( os.path.join(working_folder, file_name), file_name) if not quiet: print('.', end='') except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore added file "%s"; aborting restore...' % file_name return False output = subprocess.Popen( ['hg', 'add', file_name], stdout=subprocess.PIPE).communicate()[0].decode( "utf-8") if not len(output): add_status[file_name] = True if not quiet: print('.', end='') else: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore added file "%s":\n%s\n...aborting restore...' % ( file_name, output) return False elif status == 'M': files_are_equal = False # see if the file is unchanged by the merge; in that case, just copy it if manifest_version <= 1: new_key = get_changeset_for(options, file_name) if not new_key: if shelved_stage is not None: shutil.rmtree(stage_path) os.chdir(working_dir) self.message = 'ERROR: Failed to determine changeset for file "%s".' % file_name return False old_crc32 = crc32(os.path.join(working_folder, file_name)) new_crc32 = crc32(file_name) files_are_equal = (previous_key == new_key) and (old_crc32 == new_crc32) else: # make sure the target file hasn't changed since we last shelved new_key = hashlib.md5(open(file_name, 'rb').read()).hexdigest() files_are_equal = new_key == previous_key if options.overwrite or files_are_equal: try: shutil.copyfile( os.path.join(working_folder, file_name), file_name) if not quiet: print('.', end='') except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore modified file "%s":\n...aborting restore...' % file_name return False else: # the file has been altered, so we have to merge...see what we have available merge_tool = '' if 'PYHG_MERGE_TOOL' in os.environ: merge_tool = os.environ['PYHG_MERGE_TOOL'] elif os.name == 'nt': if len(options.winmerge): merge_tool = options.winmerge elif len(options.patch): merge_tool = options.patch elif len(options.diff): merge_tool = options.diff if len(merge_tool): previous_key = hashlib.md5( open(os.path.join(working_folder, file_name), 'rb').read()).hexdigest() os.system( '%s "%s" "%s"' % (merge_tool, os.path.join(working_folder, file_name), file_name)) new_key = hashlib.md5( open(os.path.join(working_folder, file_name), 'rb').read()).hexdigest() merge_status[file_name] = (previous_key != new_key) if previous_key != new_key: try: shutil.copyfile( os.path.join(working_folder, file_name), file_name) if not quiet: print('.', end='') except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore merged file "%s":\n...aborting restore...' % file_name return False else: print( "WARNING: Skipping '%s'; no merge performed..." % file_name, file=sys.stderr) else: if not quiet: print( "WARNING: Skipping '%s'; no merge solution available..." % file_name, file=sys.stderr) elif status == 'R': if os.path.exists(file_name): output = subprocess.Popen( ['hg', 'remove', file_name], stdout=subprocess.PIPE).communicate()[0].decode( "utf-8") if len(output): abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to remove file "%s":\n%s\n...aborting restore...' % ( file_name, output) return False else: if not quiet: print('.', end='') elif status == 'V': # rename output = '' from_name, to_name = file_name.split(',') # first, perform a 'move' (i.e., rename) on the existing file if os.path.exists(from_name): output = subprocess.Popen( ['hg', 'mv', from_name, to_name], stdout=subprocess.PIPE).communicate()[0].decode( "utf-8") if len(output): abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to rename file "%s":\n%s\n...aborting restore...' % ( from_name, output) return False # next, copy the contents of the archived version if it differs files_are_equal = False if manifest_version <= 1: old_crc32 = crc32(os.path.join(working_folder, to_name)) new_crc32 = crc32(to_name) files_are_equal = (previous_key == new_key) and (old_crc32 == new_crc32) else: new_key = hashlib.md5(open(to_name, 'rb').read()).hexdigest() files_are_equal = new_key == previous_key if options.overwrite or files_are_equal: try: shutil.copyfile(os.path.join(working_folder, to_name), to_name) if not quiet: print('.', end='') except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore renamed file "%s":\n...aborting restore...' % to_name return False else: # the file has been altered, so we have to merge...see what we have available merge_tool = '' if 'PYHG_MERGE_TOOL' in os.environ: merge_tool = os.environ['PYHG_MERGE_TOOL'] elif os.name == 'nt': if len(options.winmerge): merge_tool = options.winmerge elif len(options.patch): merge_tool = options.patch elif len(options.diff): merge_tool = options.diff if len(merge_tool): previous_key = hashlib.md5( open(os.path.join(working_folder, to_name), 'rb').read()).hexdigest() os.system( '%s "%s" "%s"' % (merge_tool, os.path.join(working_folder, to_name), to_name)) new_key = hashlib.md5( open(os.path.join(working_folder, to_name), 'rb').read()).hexdigest() merge_status[file_name] = (previous_key != new_key) if previous_key != new_key: try: shutil.copyfile( os.path.join(working_folder, to_name), to_name) if not quiet: print('.', end='') except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore merged file "%s":\n...aborting restore...' % file_name return False else: print( "WARNING: Skipping '%s'; no merge performed..." % file_name, file=sys.stderr) else: if not quiet: print( "WARNING: Skipping '%s'; no merge solution available..." % file_name, file=sys.stderr) elif status == 'X': # extra file -- just put it back where it was exactly as it was, no additional handling if os.path.exists(file_name): try: os.remove(file_name) except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to remove extra file "%s":\n...aborting restore...' % file_name return False restore_command = [ options.seven_zip, 'x', manifest_archive, file_name ] try: output = subprocess.Popen( restore_command, stdout=subprocess.PIPE).communicate()[0].decode( "utf-8") except: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore extra file "%s":\n...aborting restore...' % file_name return False something_went_wrong = True for line in output.split('\n'): line = line.rstrip() if line == 'Everything is Ok': something_went_wrong = False break if something_went_wrong: abort_cleanup(abort_cleanups) self.message = 'ERROR: Failed to restore extra file "%s":\n...aborting restore...' % file_name return False if not quiet: print('.', end='') if not quiet: for i in range(len(manifest_lines)): line = manifest_lines[i].rstrip() #status, file_name, timestamp = line.split(':') status, file_name, changeset = line.split('?') manifest_lines[i] = '%s %s' % (status, file_name) if file_name in merge_status: if not merge_status[file_name]: manifest_lines[i] = '? %s' % file_name elif file_name in add_status: if not add_status[file_name]: manifest_lines[i] = '? %s' % file_name batch_text = '' if os.name == 'nt': batch_text = '@echo off\n' batch_text += 'set FG=%_fg\n' batch_text += 'set BG=%_bg\n' manifest_lines = colorize_status(manifest_lines) print('\nRestored the following state from microbranch "%s":' % shelf_name_unquoted) for line in manifest_lines: if options.ansi_color: if options.ansi_color_requires_batch: batch_text += 'echo %s\n' % line[3] else: print(line[3]) else: print(line[0], line[1]) if options.ansi_color: if options.ansi_color_requires_batch: if os.name == 'nt': batch_text += 'color %FG on %BG\n' open(options.batch_file_name, 'w').write(batch_text) os.system(options.batch_file_name) if options.erase_cache: print('Removing cached microbranch "%s".' % shelf_name_unquoted) try: os.remove(manifest_name) os.remove(manifest_archive) except: os.chdir(working_dir) self.message = 'ERROR: Failed to remove cached files.' return False os.chdir(working_dir) return True
def execute(self, options, quiet=False, **kwargs): working_dir = os.getcwd() root = find_hg_root() if root: # set working directory to the top of the working copy os.chdir(root) os.chdir("..") root = find_mb_root( ) # this will not return if we can't find a working location shelf_name = None if len(options.shelf_name) != 0: shelf_name = quote(options.shelf_name, '') import glob files = glob.glob(os.path.join(root, '*.manifest')) if len(files) == 0: if not quiet: print('No microbranches are currently shelved.') else: if not shelf_name: if not quiet: print('The following microbranches are on the shelf:') for file in files: microbranch_name = os.path.basename(file).split('.')[0] if shelf_name and shelf_name != microbranch_name: continue if shelf_name and options.detailed: if not quiet: print( 'Microbranch "%s" caches the following changes:' % options.args[0]) manifest_file = file manifest_lines = open(manifest_file).readlines() if manifest_lines[0].startswith('version '): manifest_version = int(manifest_lines[0][8:]) del manifest_lines[0] if manifest_version == 1: manifest_comment = manifest_lines[0].rstrip() else: manifest_comment = manifest_lines[0].rstrip() del manifest_lines[0] if not quiet: if len(manifest_comment): print(' "%s" (%s)' % (microbranch_name, manifest_comment)) else: print(' "%s"' % microbranch_name) if options.detailed: for line in manifest_lines: line = line.rstrip() items = line.split('?') print(' %s -> %s' % (items[0], items[1])) os.chdir(working_dir) return True
def __init__(self, options): if not options.branch: return working_dir = os.getcwd() root = find_hg_root() if root: # set working directory to the top of the working copy os.chdir(root) os.chdir("..") if not os.path.exists('.hg'): os.chdir(working_dir) print("ERROR: Must be in root of working copy to shelf.", file=sys.stderr) sys.exit(1) shelf_name = 'shelf' if len(options.args): if sys.version_info[0] > 2: shelf_name = urllib.parse.quote(options.args[0], '') else: shelf_name = urllib.quote(options.args[0], '') root = find_mb_root( ) # this will not return if we can't find a working location manifest_file = os.path.join(root, '%s.manifest' % shelf_name) if not os.path.exists(manifest_file): if shelf_name == 'shelf': print('Working copy has no cached default microbranch.') else: print('Cannot access microbranch "%s".' % shelf_name) else: manifest_lines = open(manifest_file).readlines() del manifest_lines[0] # delete the comment conflict_count = 0 for line in manifest_lines: line = line.rstrip() if len(line) == 0: continue status, file_name, old_changeset = line.split('?') if status == 'M': if os.name == 'nt': file_name = file_name.replace('/', '\\') else: file_name = file_name.replace('\\', '/') new_changeset = get_changeset_for(options, file_name) old_crc32 = crc32(os.path.join(working_dir, file_name)) new_crc32 = crc32(file_name) if not new_changeset: print( "ERROR: Failed to determine changeset for file '%s'!" % file_name, file=sys.stderr) os.chdir(working_dir) sys.exit(1) if (old_changeset != new_changeset) or (old_crc32 != new_crc32): if conflict_count == 0: print( 'Potential conflicts detected for the following "%s" microbranch assets:' % (shelf_name if shelf_name != "shelf" else "default")) print('\t', file_name) conflict_count += 1 if conflict_count == 0: print('No potential conflicts detected for "%s" microbranch.' % (shelf_name if shelf_name != "shelf" else "default")) os.chdir(working_dir)