def conflicts(self): conflicts = _mod_conflicts.ConflictList() for conflicted in self._iter_conflicts(): text = True try: if osutils.file_kind(self.abspath(conflicted)) != "file": text = False except errors.NoSuchFile: text = False if text is True: for suffix in ('.THIS', '.OTHER'): try: kind = osutils.file_kind( self.abspath(conflicted + suffix)) if kind != "file": text = False except errors.NoSuchFile: text = False if text == False: break ctype = {True: 'text conflict', False: 'contents conflict'}[text] conflicts.append( _mod_conflicts.Conflict.factory( ctype, path=conflicted, file_id=self.path2id(conflicted))) return conflicts
def test_merge_kind_change(self): tree_a = self.make_branch_and_tree('tree_a') self.build_tree_contents([('tree_a/file', 'content_1')]) tree_a.add('file', 'file-id') tree_a.commit('added file') tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree() os.unlink('tree_a/file') self.build_tree(['tree_a/file/']) tree_a.commit('changed file to directory') self.run_bzr('merge ../tree_a', working_dir='tree_b') self.assertEqual('directory', osutils.file_kind('tree_b/file')) tree_b.revert() self.assertEqual('file', osutils.file_kind('tree_b/file')) self.build_tree_contents([('tree_b/file', 'content_2')]) tree_b.commit('content change') self.run_bzr('merge ../tree_a', retcode=1, working_dir='tree_b') self.assertEqual(tree_b.conflicts(), [conflicts.ContentsConflict('file', file_id='file-id')])
def test_merge_kind_change(self): tree_a = self.make_branch_and_tree('tree_a') self.build_tree_contents([('tree_a/file', 'content_1')]) tree_a.add('file', 'file-id') tree_a.commit('added file') tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree() os.unlink('tree_a/file') self.build_tree(['tree_a/file/']) tree_a.commit('changed file to directory') os.chdir('tree_b') self.run_bzr('merge ../tree_a') self.assertEqual('directory', file_kind('file')) tree_b.revert() self.assertEqual('file', file_kind('file')) self.build_tree_contents([('file', 'content_2')]) tree_b.commit('content change') self.run_bzr('merge ../tree_a', retcode=1) self.assertEqual(tree_b.conflicts(), [ContentsConflict('file', file_id='file-id')])
def load(self): kind = osutils.file_kind(self.filename) text = '' if kind == 'file': f = open(self.filename, 'rb') try: text = f.read() finally: f.close() elif kind == 'symlink': text = os.readlink(self.filename) self.text = text self._create_and_show_browser(self.filename, text, kind)
def conflicts(self): conflicts = _mod_conflicts.ConflictList() for conflicted in self._iter_conflicts(): text = True try: if osutils.file_kind(self.abspath(conflicted)) != "file": text = False except errors.NoSuchFile: text = False if text is True: for suffix in ('.THIS', '.OTHER'): try: kind = osutils.file_kind(self.abspath(conflicted+suffix)) if kind != "file": text = False except errors.NoSuchFile: text = False if text == False: break ctype = {True: 'text conflict', False: 'contents conflict'}[text] conflicts.append(_mod_conflicts.Conflict.factory(ctype, path=conflicted, file_id=self.path2id(conflicted))) return conflicts
def smart_add(self, file_list, recurse=True, action=None, save=True): """Version file_list, optionally recursing into directories. This is designed more towards DWIM for humans than API clarity. For the specific behaviour see the help for cmd_add(). :param action: A reporter to be called with the inventory, parent_ie, path and kind of the path being added. It may return a file_id if a specific one should be used. :param save: Save the inventory after completing the adds. If False this provides dry-run functionality by doing the add and not saving the inventory. :return: A tuple - files_added, ignored_files. files_added is the count of added files, and ignored_files is a dict mapping files that were ignored to the rule that caused them to be ignored. """ # not in an inner loop; and we want to remove direct use of this, # so here as a reminder for now. RBC 20070703 from bzrlib.inventory import InventoryEntry if action is None: action = add.AddAction() if not file_list: # no paths supplied: add the entire tree. file_list = [u'.'] # mutter("smart add of %r") inv = self.inventory added = [] ignored = {} dirs_to_add = [] user_dirs = set() # validate user file paths and convert all paths to tree # relative : it's cheaper to make a tree relative path an abspath # than to convert an abspath to tree relative. for filepath in file_list: rf = _FastPath(self.relpath(filepath)) # validate user parameters. Our recursive code avoids adding new files # that need such validation if self.is_control_filename(rf.raw_path): raise errors.ForbiddenControlFileError(filename=rf.raw_path) abspath = self.abspath(rf.raw_path) kind = osutils.file_kind(abspath) if kind == 'directory': # schedule the dir for scanning user_dirs.add(rf) else: if not InventoryEntry.versionable_kind(kind): raise errors.BadFileKindError(filename=abspath, kind=kind) # ensure the named path is added, so that ignore rules in the later directory # walk dont skip it. # we dont have a parent ie known yet.: use the relatively slower inventory # probing method versioned = inv.has_filename(rf.raw_path) if versioned: continue added.extend(_add_one_and_parent(self, inv, None, rf, kind, action)) if not recurse: # no need to walk any directories at all. if len(added) > 0 and save: self._write_inventory(inv) return added, ignored # only walk the minimal parents needed: we have user_dirs to override # ignores. prev_dir = None is_inside = osutils.is_inside_or_parent_of_any for path in sorted(user_dirs): if (prev_dir is None or not is_inside([prev_dir], path.raw_path)): dirs_to_add.append((path, None)) prev_dir = path.raw_path # dirs_to_add is initialised to a list of directories, but as we scan # directories we append files to it. # XXX: We should determine kind of files when we scan them rather than # adding to this list. RBC 20070703 for directory, parent_ie in dirs_to_add: # directory is tree-relative abspath = self.abspath(directory.raw_path) # get the contents of this directory. # find the kind of the path being added. kind = osutils.file_kind(abspath) if not InventoryEntry.versionable_kind(kind): warning("skipping %s (can't add file of kind '%s')", abspath, kind) continue if parent_ie is not None: versioned = directory.base_path in parent_ie.children else: # without the parent ie, use the relatively slower inventory # probing method versioned = inv.has_filename(directory.raw_path) if kind == 'directory': try: sub_branch = bzrdir.BzrDir.open(abspath) sub_tree = True except errors.NotBranchError: sub_tree = False except errors.UnsupportedFormatError: sub_tree = True else: sub_tree = False if directory.raw_path == '': # mutter("tree root doesn't need to be added") sub_tree = False elif versioned: pass # mutter("%r is already versioned", abspath) elif sub_tree: # XXX: This is wrong; people *might* reasonably be trying to add # subtrees as subtrees. This should probably only be done in formats # which can represent subtrees, and even then perhaps only when # the user asked to add subtrees. At the moment you can add them # specially through 'join --reference', which is perhaps # reasonable: adding a new reference is a special operation and # can have a special behaviour. mbp 20070306 mutter("%r is a nested bzr tree", abspath) else: _add_one(self, inv, parent_ie, directory, kind, action) added.append(directory.raw_path) if kind == 'directory' and not sub_tree: if parent_ie is not None: # must be present: this_ie = parent_ie.children[directory.base_path] else: # without the parent ie, use the relatively slower inventory # probing method this_id = inv.path2id(directory.raw_path) if this_id is None: this_ie = None else: this_ie = inv[this_id] for subf in sorted(os.listdir(abspath)): # here we could use TreeDirectory rather than # string concatenation. subp = osutils.pathjoin(directory.raw_path, subf) # TODO: is_control_filename is very slow. Make it faster. # TreeDirectory.is_control_filename could also make this # faster - its impossible for a non root dir to have a # control file. if self.is_control_filename(subp): mutter("skip control directory %r", subp) elif subf in this_ie.children: # recurse into this already versioned subdir. dirs_to_add.append((_FastPath(subp, subf), this_ie)) else: # user selection overrides ignoes # ignore while selecting files - if we globbed in the # outer loop we would ignore user files. ignore_glob = self.is_ignored(subp) if ignore_glob is not None: # mutter("skip ignored sub-file %r", subp) ignored.setdefault(ignore_glob, []).append(subp) else: #mutter("queue to add sub-file %r", subp) dirs_to_add.append((_FastPath(subp, subf), this_ie)) if len(added) > 0: if save: self._write_inventory(inv) else: self.read_working_inventory() return added, ignored