~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

  • Committer: Vincent Ladeuil
  • Date: 2009-07-02 13:07:14 UTC
  • mto: (4524.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4525.
  • Revision ID: v.ladeuil+lp@free.fr-20090702130714-hsyqfusi8vn3a11m
Use tree.has_changes() where appropriate (the test suite caught a
bug in has_changes() (not filtering out the root) in an impressive
number of tests)

* bzrlib/send.py:
(send): Use tree.has_changes() instead of tree.changes_from().

* bzrlib/reconfigure.py:
(Reconfigure._check): Use tree.has_changes() instead of
tree.changes_from().

* bzrlib/merge.py:
(Merger.ensure_revision_trees, Merger.compare_basis): Use
tree.has_changes() instead of tree.changes_from().

* bzrlib/builtins.py:
(cmd_remove_tree.run, cmd_push.run, cmd_merge.run): Use
tree.has_changes() instead of tree.changes_from().

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import difflib
18
18
import os
36
36
    patiencediff,
37
37
    textfile,
38
38
    timestamp,
 
39
    views,
39
40
    )
40
41
""")
41
42
 
42
43
from bzrlib.symbol_versioning import (
43
 
        deprecated_function,
44
 
        one_three
45
 
        )
46
 
from bzrlib.trace import warning
 
44
    deprecated_function,
 
45
    )
 
46
from bzrlib.trace import mutter, note, warning
47
47
 
48
48
 
49
49
# TODO: Rather than building a changeset object, we should probably
78
78
    # both sequences are empty.
79
79
    if not oldlines and not newlines:
80
80
        return
81
 
    
 
81
 
82
82
    if allow_binary is False:
83
83
        textfile.check_text_lines(oldlines)
84
84
        textfile.check_text_lines(newlines)
199
199
            break
200
200
        else:
201
201
            diffcmd.append('-u')
202
 
                  
 
202
 
203
203
        if diff_opts:
204
204
            diffcmd.extend(diff_opts)
205
205
 
206
206
        pipe = _spawn_external_diff(diffcmd, capture_errors=True)
207
207
        out,err = pipe.communicate()
208
208
        rc = pipe.returncode
209
 
        
 
209
 
210
210
        # internal_diff() adds a trailing newline, add one here for consistency
211
211
        out += '\n'
212
212
        if rc == 2:
247
247
                msg = 'signal %d' % (-rc)
248
248
            else:
249
249
                msg = 'exit code %d' % rc
250
 
                
251
 
            raise errors.BzrError('external diff failed with %s; command: %r' 
 
250
 
 
251
            raise errors.BzrError('external diff failed with %s; command: %r'
252
252
                                  % (rc, diffcmd))
253
253
 
254
254
 
272
272
                        new_abspath, e)
273
273
 
274
274
 
275
 
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
 
275
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url,
 
276
    apply_view=True):
276
277
    """Get the trees and specific files to diff given a list of paths.
277
278
 
278
279
    This method works out the trees to be diff'ed and the files of
289
290
    :param new_url:
290
291
        The url of the new branch or tree. If None, the tree to use is
291
292
        taken from the first path, if any, or the current working tree.
 
293
    :param apply_view:
 
294
        if True and a view is set, apply the view or check that the paths
 
295
        are within it
292
296
    :returns:
293
297
        a tuple of (old_tree, new_tree, specific_files, extra_trees) where
294
298
        extra_trees is a sequence of additional trees to search in for
328
332
    working_tree, branch, relpath = \
329
333
        bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
330
334
    if consider_relpath and relpath != '':
 
335
        if working_tree is not None and apply_view:
 
336
            views.check_path_in_view(working_tree, relpath)
331
337
        specific_files.append(relpath)
332
338
    old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
333
339
 
338
344
        working_tree, branch, relpath = \
339
345
            bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
340
346
        if consider_relpath and relpath != '':
 
347
            if working_tree is not None and apply_view:
 
348
                views.check_path_in_view(working_tree, relpath)
341
349
            specific_files.append(relpath)
342
350
    new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
343
351
        basis_is_default=working_tree is None)
344
352
 
345
353
    # Get the specific files (all files is None, no files is [])
346
354
    if make_paths_wt_relative and working_tree is not None:
347
 
        other_paths = _relative_paths_in_tree(working_tree, other_paths)
 
355
        try:
 
356
            from bzrlib.builtins import safe_relpath_files
 
357
            other_paths = safe_relpath_files(working_tree, other_paths,
 
358
            apply_view=apply_view)
 
359
        except errors.FileInWrongBranch:
 
360
            raise errors.BzrCommandError("Files are in different branches")
348
361
    specific_files.extend(other_paths)
349
362
    if len(specific_files) == 0:
350
363
        specific_files = None
 
364
        if (working_tree is not None and working_tree.supports_views()
 
365
            and apply_view):
 
366
            view_files = working_tree.views.lookup_view()
 
367
            if view_files:
 
368
                specific_files = view_files
 
369
                view_str = views.view_display_str(view_files)
 
370
                note("*** Ignoring files outside view. View is %s" % view_str)
351
371
 
352
372
    # Get extra trees that ought to be searched for file-ids
353
373
    extra_trees = None
355
375
        extra_trees = (working_tree,)
356
376
    return old_tree, new_tree, specific_files, extra_trees
357
377
 
358
 
 
359
378
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
360
379
    if branch is None and tree is not None:
361
380
        branch = tree.branch
370
389
    return spec.as_tree(branch)
371
390
 
372
391
 
373
 
def _relative_paths_in_tree(tree, paths):
374
 
    """Get the relative paths within a working tree.
375
 
 
376
 
    Each path may be either an absolute path or a path relative to the
377
 
    current working directory.
378
 
    """
379
 
    result = []
380
 
    for filename in paths:
381
 
        try:
382
 
            result.append(tree.relpath(osutils.dereference_path(filename)))
383
 
        except errors.PathNotChild:
384
 
            raise errors.BzrCommandError("Files are in different branches")
385
 
    return result
386
 
 
387
 
 
388
392
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
389
393
                    external_diff_options=None,
390
394
                    old_label='a/', new_label='b/',
436
440
    return timestamp.format_patch_date(mtime)
437
441
 
438
442
 
439
 
@deprecated_function(one_three)
440
 
def get_prop_change(meta_modified):
441
 
    if meta_modified:
442
 
        return " (properties changed)"
443
 
    else:
444
 
        return  ""
445
 
 
446
443
def get_executable_change(old_is_x, new_is_x):
447
444
    descr = { True:"+x", False:"-x", None:"??" }
448
445
    if old_is_x != new_is_x:
623
620
            return self.CANNOT_DIFF
624
621
        from_label = '%s%s\t%s' % (self.old_label, old_path, old_date)
625
622
        to_label = '%s%s\t%s' % (self.new_label, new_path, new_date)
626
 
        return self.diff_text(from_file_id, to_file_id, from_label, to_label)
 
623
        return self.diff_text(from_file_id, to_file_id, from_label, to_label,
 
624
            old_path, new_path)
627
625
 
628
 
    def diff_text(self, from_file_id, to_file_id, from_label, to_label):
 
626
    def diff_text(self, from_file_id, to_file_id, from_label, to_label,
 
627
        from_path=None, to_path=None):
629
628
        """Diff the content of given files in two trees
630
629
 
631
630
        :param from_file_id: The id of the file in the from tree.  If None,
633
632
        :param to_file_id: The id of the file in the to tree.  This may refer
634
633
            to a different file from from_file_id.  If None,
635
634
            the file is not present in the to tree.
 
635
        :param from_path: The path in the from tree or None if unknown.
 
636
        :param to_path: The path in the to tree or None if unknown.
636
637
        """
637
 
        def _get_text(tree, file_id):
 
638
        def _get_text(tree, file_id, path):
638
639
            if file_id is not None:
639
 
                return tree.get_file(file_id).readlines()
 
640
                return tree.get_file(file_id, path).readlines()
640
641
            else:
641
642
                return []
642
643
        try:
643
 
            from_text = _get_text(self.old_tree, from_file_id)
644
 
            to_text = _get_text(self.new_tree, to_file_id)
 
644
            from_text = _get_text(self.old_tree, from_file_id, from_path)
 
645
            to_text = _get_text(self.new_tree, to_file_id, to_path)
645
646
            self.text_differ(from_label, from_text, to_label, to_text,
646
647
                             self.to_file)
647
648
        except errors.BinaryFile:
734
735
        return old_disk_path, new_disk_path
735
736
 
736
737
    def finish(self):
737
 
        osutils.rmtree(self._root)
 
738
        try:
 
739
            osutils.rmtree(self._root)
 
740
        except OSError, e:
 
741
            if e.errno != errno.ENOENT:
 
742
                mutter("The temporary directory \"%s\" was not "
 
743
                        "cleanly removed: %s." % (self._root, e))
738
744
 
739
745
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
740
746
        if (old_kind, new_kind) != ('file', 'file'):
885
891
                self.to_file.write("=== modified %s '%s'%s\n" % (kind[0],
886
892
                                   newpath_encoded, prop_str))
887
893
            if changed_content:
888
 
                self.diff(file_id, oldpath, newpath)
 
894
                self._diff(file_id, oldpath, newpath, kind[0], kind[1])
889
895
                has_changes = 1
890
896
            if renamed:
891
897
                has_changes = 1
906
912
            new_kind = self.new_tree.kind(file_id)
907
913
        except (errors.NoSuchId, errors.NoSuchFile):
908
914
            new_kind = None
909
 
 
 
915
        self._diff(file_id, old_path, new_path, old_kind, new_kind)
 
916
 
 
917
 
 
918
    def _diff(self, file_id, old_path, new_path, old_kind, new_kind):
910
919
        result = DiffPath._diff_many(self.differs, file_id, old_path,
911
920
                                       new_path, old_kind, new_kind)
912
921
        if result is DiffPath.CANNOT_DIFF: