~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/weave.py

  • Committer: Aaron Bentley
  • Date: 2009-03-24 15:47:32 UTC
  • mto: This revision was merged to the branch mainline in revision 4241.
  • Revision ID: aaron@aaronbentley.com-20090324154732-bwkvi4dx3o90a7dq
Add output, emit minimal inventory delta.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2009 Canonical Ltd
 
1
#! /usr/bin/python
 
2
 
 
3
# Copyright (C) 2005 Canonical Ltd
2
4
#
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
69
71
from copy import copy
70
72
from cStringIO import StringIO
71
73
import os
 
74
import time
 
75
import warnings
72
76
 
73
77
from bzrlib.lazy_import import lazy_import
74
78
lazy_import(globals(), """
77
81
from bzrlib import (
78
82
    errors,
79
83
    osutils,
 
84
    progress,
80
85
    )
81
86
from bzrlib.errors import (WeaveError, WeaveFormatError, WeaveParentMismatch,
82
87
        RevisionAlreadyPresent,
83
88
        RevisionNotPresent,
84
89
        UnavailableRepresentation,
 
90
        WeaveRevisionAlreadyPresent,
 
91
        WeaveRevisionNotPresent,
85
92
        )
86
93
from bzrlib.osutils import dirname, sha, sha_strings, split_lines
87
94
import bzrlib.patiencediff
403
410
        version_id
404
411
            Symbolic name for this version.
405
412
            (Typically the revision-id of the revision that added it.)
406
 
            If None, a name will be allocated based on the hash. (sha1:SHAHASH)
407
413
 
408
414
        parents
409
415
            List or set of direct parent version numbers.
419
425
            sha1 = sha_strings(lines)
420
426
        if sha1 == nostore_sha:
421
427
            raise errors.ExistingContent
422
 
        if version_id is None:
423
 
            version_id = "sha1:" + sha1
424
428
        if version_id in self._name_map:
425
429
            return self._check_repeated_add(version_id, parents, lines, sha1)
426
430
 
1018
1022
        wr._add(name, lines, [wr._lookup(i) for i in combined_parents[name]])
1019
1023
    return wr
1020
1024
 
1021
 
 
1022
1025
def _reweave_parent_graphs(wa, wb):
1023
1026
    """Return combined parent ancestry for two weaves.
1024
1027
 
1029
1032
            p = combined.setdefault(name, set())
1030
1033
            p.update(map(weave._idx_to_name, weave._parents[idx]))
1031
1034
    return combined
 
1035
 
 
1036
 
 
1037
def weave_toc(w):
 
1038
    """Show the weave's table-of-contents"""
 
1039
    print '%6s %50s %10s %10s' % ('ver', 'name', 'sha1', 'parents')
 
1040
    for i in (6, 50, 10, 10):
 
1041
        print '-' * i,
 
1042
    print
 
1043
    for i in range(w.num_versions()):
 
1044
        sha1 = w._sha1s[i]
 
1045
        name = w._names[i]
 
1046
        parent_str = ' '.join(map(str, w._parents[i]))
 
1047
        print '%6d %-50.50s %10.10s %s' % (i, name, sha1, parent_str)
 
1048
 
 
1049
 
 
1050
 
 
1051
def weave_stats(weave_file, pb):
 
1052
    from bzrlib.weavefile import read_weave
 
1053
 
 
1054
    wf = file(weave_file, 'rb')
 
1055
    w = read_weave(wf)
 
1056
    # FIXME: doesn't work on pipes
 
1057
    weave_size = wf.tell()
 
1058
 
 
1059
    total = 0
 
1060
    vers = len(w)
 
1061
    for i in range(vers):
 
1062
        pb.update('checking sizes', i, vers)
 
1063
        for origin, lineno, line in w._extract([i]):
 
1064
            total += len(line)
 
1065
 
 
1066
    pb.clear()
 
1067
 
 
1068
    print 'versions          %9d' % vers
 
1069
    print 'weave file        %9d bytes' % weave_size
 
1070
    print 'total contents    %9d bytes' % total
 
1071
    print 'compression ratio %9.2fx' % (float(total) / float(weave_size))
 
1072
    if vers:
 
1073
        avg = total/vers
 
1074
        print 'average size      %9d bytes' % avg
 
1075
        print 'relative size     %9.2fx' % (float(weave_size) / float(avg))
 
1076
 
 
1077
 
 
1078
def usage():
 
1079
    print """bzr weave tool
 
1080
 
 
1081
Experimental tool for weave algorithm.
 
1082
 
 
1083
usage:
 
1084
    weave init WEAVEFILE
 
1085
        Create an empty weave file
 
1086
    weave get WEAVEFILE VERSION
 
1087
        Write out specified version.
 
1088
    weave check WEAVEFILE
 
1089
        Check consistency of all versions.
 
1090
    weave toc WEAVEFILE
 
1091
        Display table of contents.
 
1092
    weave add WEAVEFILE NAME [BASE...] < NEWTEXT
 
1093
        Add NEWTEXT, with specified parent versions.
 
1094
    weave annotate WEAVEFILE VERSION
 
1095
        Display origin of each line.
 
1096
    weave merge WEAVEFILE VERSION1 VERSION2 > OUT
 
1097
        Auto-merge two versions and display conflicts.
 
1098
    weave diff WEAVEFILE VERSION1 VERSION2
 
1099
        Show differences between two versions.
 
1100
 
 
1101
example:
 
1102
 
 
1103
    % weave init foo.weave
 
1104
    % vi foo.txt
 
1105
    % weave add foo.weave ver0 < foo.txt
 
1106
    added version 0
 
1107
 
 
1108
    (create updated version)
 
1109
    % vi foo.txt
 
1110
    % weave get foo.weave 0 | diff -u - foo.txt
 
1111
    % weave add foo.weave ver1 0 < foo.txt
 
1112
    added version 1
 
1113
 
 
1114
    % weave get foo.weave 0 > foo.txt       (create forked version)
 
1115
    % vi foo.txt
 
1116
    % weave add foo.weave ver2 0 < foo.txt
 
1117
    added version 2
 
1118
 
 
1119
    % weave merge foo.weave 1 2 > foo.txt   (merge them)
 
1120
    % vi foo.txt                            (resolve conflicts)
 
1121
    % weave add foo.weave merged 1 2 < foo.txt     (commit merged version)
 
1122
 
 
1123
"""
 
1124
 
 
1125
 
 
1126
 
 
1127
def main(argv):
 
1128
    import sys
 
1129
    import os
 
1130
    try:
 
1131
        import bzrlib
 
1132
    except ImportError:
 
1133
        # in case we're run directly from the subdirectory
 
1134
        sys.path.append('..')
 
1135
        import bzrlib
 
1136
    from bzrlib.weavefile import write_weave, read_weave
 
1137
    from bzrlib.progress import ProgressBar
 
1138
 
 
1139
    try:
 
1140
        import psyco
 
1141
        psyco.full()
 
1142
    except ImportError:
 
1143
        pass
 
1144
 
 
1145
    if len(argv) < 2:
 
1146
        usage()
 
1147
        return 0
 
1148
 
 
1149
    cmd = argv[1]
 
1150
 
 
1151
    def readit():
 
1152
        return read_weave(file(argv[2], 'rb'))
 
1153
 
 
1154
    if cmd == 'help':
 
1155
        usage()
 
1156
    elif cmd == 'add':
 
1157
        w = readit()
 
1158
        # at the moment, based on everything in the file
 
1159
        name = argv[3]
 
1160
        parents = map(int, argv[4:])
 
1161
        lines = sys.stdin.readlines()
 
1162
        ver = w.add(name, parents, lines)
 
1163
        write_weave(w, file(argv[2], 'wb'))
 
1164
        print 'added version %r %d' % (name, ver)
 
1165
    elif cmd == 'init':
 
1166
        fn = argv[2]
 
1167
        if os.path.exists(fn):
 
1168
            raise IOError("file exists")
 
1169
        w = Weave()
 
1170
        write_weave(w, file(fn, 'wb'))
 
1171
    elif cmd == 'get': # get one version
 
1172
        w = readit()
 
1173
        sys.stdout.writelines(w.get_iter(int(argv[3])))
 
1174
 
 
1175
    elif cmd == 'diff':
 
1176
        w = readit()
 
1177
        fn = argv[2]
 
1178
        v1, v2 = map(int, argv[3:5])
 
1179
        lines1 = w.get(v1)
 
1180
        lines2 = w.get(v2)
 
1181
        diff_gen = bzrlib.patiencediff.unified_diff(lines1, lines2,
 
1182
                                '%s version %d' % (fn, v1),
 
1183
                                '%s version %d' % (fn, v2))
 
1184
        sys.stdout.writelines(diff_gen)
 
1185
 
 
1186
    elif cmd == 'annotate':
 
1187
        w = readit()
 
1188
        # newline is added to all lines regardless; too hard to get
 
1189
        # reasonable formatting otherwise
 
1190
        lasto = None
 
1191
        for origin, text in w.annotate(int(argv[3])):
 
1192
            text = text.rstrip('\r\n')
 
1193
            if origin == lasto:
 
1194
                print '      | %s' % (text)
 
1195
            else:
 
1196
                print '%5d | %s' % (origin, text)
 
1197
                lasto = origin
 
1198
 
 
1199
    elif cmd == 'toc':
 
1200
        weave_toc(readit())
 
1201
 
 
1202
    elif cmd == 'stats':
 
1203
        weave_stats(argv[2], ProgressBar())
 
1204
 
 
1205
    elif cmd == 'check':
 
1206
        w = readit()
 
1207
        pb = ProgressBar()
 
1208
        w.check(pb)
 
1209
        pb.clear()
 
1210
        print '%d versions ok' % w.num_versions()
 
1211
 
 
1212
    elif cmd == 'inclusions':
 
1213
        w = readit()
 
1214
        print ' '.join(map(str, w.inclusions([int(argv[3])])))
 
1215
 
 
1216
    elif cmd == 'parents':
 
1217
        w = readit()
 
1218
        print ' '.join(map(str, w._parents[int(argv[3])]))
 
1219
 
 
1220
    elif cmd == 'plan-merge':
 
1221
        # replaced by 'bzr weave-plan-merge'
 
1222
        w = readit()
 
1223
        for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
 
1224
            if line:
 
1225
                print '%14s | %s' % (state, line),
 
1226
    elif cmd == 'merge':
 
1227
        # replaced by 'bzr weave-merge-text'
 
1228
        w = readit()
 
1229
        p = w.plan_merge(int(argv[3]), int(argv[4]))
 
1230
        sys.stdout.writelines(w.weave_merge(p))
 
1231
    else:
 
1232
        raise ValueError('unknown command %r' % cmd)
 
1233
 
 
1234
 
 
1235
if __name__ == '__main__':
 
1236
    import sys
 
1237
    sys.exit(main(sys.argv))