~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commit.py

  • Committer: Martin Pool
  • Date: 2005-05-17 06:56:16 UTC
  • Revision ID: mbp@sourcefrog.net-20050517065616-6f23381d6184a8aa
- add space for un-merged patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
    from revision import Revision
65
65
    from trace import mutter, note
66
66
 
67
 
    branch.lock_write()
68
 
 
69
 
    try:
70
 
        # First walk over the working inventory; and both update that
71
 
        # and also build a new revision inventory.  The revision
72
 
        # inventory needs to hold the text-id, sha1 and size of the
73
 
        # actual file versions committed in the revision.  (These are
74
 
        # not present in the working inventory.)  We also need to
75
 
        # detect missing/deleted files, and remove them from the
76
 
        # working inventory.
77
 
 
78
 
        work_tree = branch.working_tree()
79
 
        work_inv = work_tree.inventory
80
 
        inv = Inventory()
81
 
        basis = branch.basis_tree()
82
 
        basis_inv = basis.inventory
83
 
        missing_ids = []
84
 
 
85
 
        if verbose:
86
 
            note('looking for changes...')
87
 
 
88
 
        for path, entry in work_inv.iter_entries():
89
 
            ## TODO: Check that the file kind has not changed from the previous
90
 
            ## revision of this file (if any).
91
 
 
92
 
            entry = entry.copy()
93
 
 
94
 
            p = branch.abspath(path)
95
 
            file_id = entry.file_id
96
 
            mutter('commit prep file %s, id %r ' % (p, file_id))
97
 
 
98
 
            if specific_files and not is_inside_any(specific_files, path):
99
 
                if basis_inv.has_id(file_id):
100
 
                    # carry over with previous state
101
 
                    inv.add(basis_inv[file_id].copy())
102
 
                else:
103
 
                    # omit this from committed inventory
104
 
                    pass
105
 
                continue
106
 
 
107
 
            if not work_tree.has_id(file_id):
 
67
    branch._need_writelock()
 
68
 
 
69
    # First walk over the working inventory; and both update that
 
70
    # and also build a new revision inventory.  The revision
 
71
    # inventory needs to hold the text-id, sha1 and size of the
 
72
    # actual file versions committed in the revision.  (These are
 
73
    # not present in the working inventory.)  We also need to
 
74
    # detect missing/deleted files, and remove them from the
 
75
    # working inventory.
 
76
 
 
77
    work_tree = branch.working_tree()
 
78
    work_inv = work_tree.inventory
 
79
    inv = Inventory()
 
80
    basis = branch.basis_tree()
 
81
    basis_inv = basis.inventory
 
82
    missing_ids = []
 
83
 
 
84
    if verbose:
 
85
        note('looking for changes...')
 
86
        
 
87
    for path, entry in work_inv.iter_entries():
 
88
        ## TODO: Check that the file kind has not changed from the previous
 
89
        ## revision of this file (if any).
 
90
 
 
91
        entry = entry.copy()
 
92
 
 
93
        p = branch.abspath(path)
 
94
        file_id = entry.file_id
 
95
        mutter('commit prep file %s, id %r ' % (p, file_id))
 
96
 
 
97
        if specific_files and not is_inside_any(specific_files, path):
 
98
            if basis_inv.has_id(file_id):
 
99
                # carry over with previous state
 
100
                inv.add(basis_inv[file_id].copy())
 
101
            else:
 
102
                # omit this from committed inventory
 
103
                pass
 
104
            continue
 
105
 
 
106
        if not work_tree.has_id(file_id):
 
107
            if verbose:
 
108
                print('deleted %s%s' % (path, kind_marker(entry.kind)))
 
109
            mutter("    file is missing, removing from inventory")
 
110
            missing_ids.append(file_id)
 
111
            continue
 
112
 
 
113
        inv.add(entry)
 
114
 
 
115
        if basis_inv.has_id(file_id):
 
116
            old_kind = basis_inv[file_id].kind
 
117
            if old_kind != entry.kind:
 
118
                raise BzrError("entry %r changed kind from %r to %r"
 
119
                        % (file_id, old_kind, entry.kind))
 
120
 
 
121
        if entry.kind == 'directory':
 
122
            if not isdir(p):
 
123
                raise BzrError("%s is entered as directory but not a directory"
 
124
                               % quotefn(p))
 
125
        elif entry.kind == 'file':
 
126
            if not isfile(p):
 
127
                raise BzrError("%s is entered as file but is not a file" % quotefn(p))
 
128
 
 
129
            new_sha1 = work_tree.get_file_sha1(file_id)
 
130
 
 
131
            old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
 
132
            if (old_ie
 
133
                and old_ie.text_sha1 == new_sha1):
 
134
                ## assert content == basis.get_file(file_id).read()
 
135
                entry.text_id = old_ie.text_id
 
136
                entry.text_sha1 = new_sha1
 
137
                entry.text_size = old_ie.text_size
 
138
                mutter('    unchanged from previous text_id {%s}' %
 
139
                       entry.text_id)
 
140
            else:
 
141
                content = file(p, 'rb').read()
 
142
 
 
143
                # calculate the sha again, just in case the file contents
 
144
                # changed since we updated the cache
 
145
                entry.text_sha1 = sha_string(content)
 
146
                entry.text_size = len(content)
 
147
 
 
148
                entry.text_id = gen_file_id(entry.name)
 
149
                branch.text_store.add(content, entry.text_id)
 
150
                mutter('    stored with text_id {%s}' % entry.text_id)
108
151
                if verbose:
109
 
                    print('deleted %s%s' % (path, kind_marker(entry.kind)))
110
 
                mutter("    file is missing, removing from inventory")
111
 
                missing_ids.append(file_id)
112
 
                continue
113
 
 
114
 
            inv.add(entry)
115
 
 
116
 
            if basis_inv.has_id(file_id):
117
 
                old_kind = basis_inv[file_id].kind
118
 
                if old_kind != entry.kind:
119
 
                    raise BzrError("entry %r changed kind from %r to %r"
120
 
                            % (file_id, old_kind, entry.kind))
121
 
 
122
 
            if entry.kind == 'directory':
123
 
                if not isdir(p):
124
 
                    raise BzrError("%s is entered as directory but not a directory"
125
 
                                   % quotefn(p))
126
 
            elif entry.kind == 'file':
127
 
                if not isfile(p):
128
 
                    raise BzrError("%s is entered as file but is not a file" % quotefn(p))
129
 
 
130
 
                new_sha1 = work_tree.get_file_sha1(file_id)
131
 
 
132
 
                old_ie = basis_inv.has_id(file_id) and basis_inv[file_id]
133
 
                if (old_ie
134
 
                    and old_ie.text_sha1 == new_sha1):
135
 
                    ## assert content == basis.get_file(file_id).read()
136
 
                    entry.text_id = old_ie.text_id
137
 
                    entry.text_sha1 = new_sha1
138
 
                    entry.text_size = old_ie.text_size
139
 
                    mutter('    unchanged from previous text_id {%s}' %
140
 
                           entry.text_id)
141
 
                else:
142
 
                    content = file(p, 'rb').read()
143
 
 
144
 
                    # calculate the sha again, just in case the file contents
145
 
                    # changed since we updated the cache
146
 
                    entry.text_sha1 = sha_string(content)
147
 
                    entry.text_size = len(content)
148
 
 
149
 
                    entry.text_id = gen_file_id(entry.name)
150
 
                    branch.text_store.add(content, entry.text_id)
151
 
                    mutter('    stored with text_id {%s}' % entry.text_id)
152
 
                    if verbose:
153
 
                        if not old_ie:
154
 
                            print('added %s' % path)
155
 
                        elif (old_ie.name == entry.name
156
 
                              and old_ie.parent_id == entry.parent_id):
157
 
                            print('modified %s' % path)
158
 
                        else:
159
 
                            print('renamed %s' % path)
160
 
 
161
 
 
162
 
        for file_id in missing_ids:
163
 
            # Any files that have been deleted are now removed from the
164
 
            # working inventory.  Files that were not selected for commit
165
 
            # are left as they were in the working inventory and ommitted
166
 
            # from the revision inventory.
167
 
 
168
 
            # have to do this later so we don't mess up the iterator.
169
 
            # since parents may be removed before their children we
170
 
            # have to test.
171
 
 
172
 
            # FIXME: There's probably a better way to do this; perhaps
173
 
            # the workingtree should know how to filter itbranch.
174
 
            if work_inv.has_id(file_id):
175
 
                del work_inv[file_id]
176
 
 
177
 
 
178
 
        if rev_id is None:
179
 
            rev_id = _gen_revision_id(time.time())
180
 
        inv_id = rev_id
181
 
 
182
 
        inv_tmp = tempfile.TemporaryFile()
183
 
        inv.write_xml(inv_tmp)
184
 
        inv_tmp.seek(0)
185
 
        branch.inventory_store.add(inv_tmp, inv_id)
186
 
        mutter('new inventory_id is {%s}' % inv_id)
187
 
 
188
 
        branch._write_inventory(work_inv)
189
 
 
190
 
        if timestamp == None:
191
 
            timestamp = time.time()
192
 
 
193
 
        if committer == None:
194
 
            committer = username()
195
 
 
196
 
        if timezone == None:
197
 
            timezone = local_time_offset()
198
 
 
199
 
        mutter("building commit log message")
200
 
        rev = Revision(timestamp=timestamp,
201
 
                       timezone=timezone,
202
 
                       committer=committer,
203
 
                       precursor = branch.last_patch(),
204
 
                       message = message,
205
 
                       inventory_id=inv_id,
206
 
                       revision_id=rev_id)
207
 
 
208
 
        rev_tmp = tempfile.TemporaryFile()
209
 
        rev.write_xml(rev_tmp)
210
 
        rev_tmp.seek(0)
211
 
        branch.revision_store.add(rev_tmp, rev_id)
212
 
        mutter("new revision_id is {%s}" % rev_id)
213
 
 
214
 
        ## XXX: Everything up to here can simply be orphaned if we abort
215
 
        ## the commit; it will leave junk files behind but that doesn't
216
 
        ## matter.
217
 
 
218
 
        ## TODO: Read back the just-generated changeset, and make sure it
219
 
        ## applies and recreates the right state.
220
 
 
221
 
        ## TODO: Also calculate and store the inventory SHA1
222
 
        mutter("committing patch r%d" % (branch.revno() + 1))
223
 
 
224
 
        branch.append_revision(rev_id)
225
 
 
226
 
        if verbose:
227
 
            note("commited r%d" % branch.revno())
228
 
    finally:
229
 
        branch.unlock()
 
152
                    if not old_ie:
 
153
                        print('added %s' % path)
 
154
                    elif (old_ie.name == entry.name
 
155
                          and old_ie.parent_id == entry.parent_id):
 
156
                        print('modified %s' % path)
 
157
                    else:
 
158
                        print('renamed %s' % path)
 
159
 
 
160
 
 
161
    for file_id in missing_ids:
 
162
        # Any files that have been deleted are now removed from the
 
163
        # working inventory.  Files that were not selected for commit
 
164
        # are left as they were in the working inventory and ommitted
 
165
        # from the revision inventory.
 
166
        
 
167
        # have to do this later so we don't mess up the iterator.
 
168
        # since parents may be removed before their children we
 
169
        # have to test.
 
170
 
 
171
        # FIXME: There's probably a better way to do this; perhaps
 
172
        # the workingtree should know how to filter itbranch.
 
173
        if work_inv.has_id(file_id):
 
174
            del work_inv[file_id]
 
175
 
 
176
 
 
177
    if rev_id is None:
 
178
        rev_id = _gen_revision_id(time.time())
 
179
    inv_id = rev_id
 
180
 
 
181
    inv_tmp = tempfile.TemporaryFile()
 
182
    inv.write_xml(inv_tmp)
 
183
    inv_tmp.seek(0)
 
184
    branch.inventory_store.add(inv_tmp, inv_id)
 
185
    mutter('new inventory_id is {%s}' % inv_id)
 
186
 
 
187
    branch._write_inventory(work_inv)
 
188
 
 
189
    if timestamp == None:
 
190
        timestamp = time.time()
 
191
 
 
192
    if committer == None:
 
193
        committer = username()
 
194
 
 
195
    if timezone == None:
 
196
        timezone = local_time_offset()
 
197
 
 
198
    mutter("building commit log message")
 
199
    rev = Revision(timestamp=timestamp,
 
200
                   timezone=timezone,
 
201
                   committer=committer,
 
202
                   precursor = branch.last_patch(),
 
203
                   message = message,
 
204
                   inventory_id=inv_id,
 
205
                   revision_id=rev_id)
 
206
 
 
207
    rev_tmp = tempfile.TemporaryFile()
 
208
    rev.write_xml(rev_tmp)
 
209
    rev_tmp.seek(0)
 
210
    branch.revision_store.add(rev_tmp, rev_id)
 
211
    mutter("new revision_id is {%s}" % rev_id)
 
212
 
 
213
    ## XXX: Everything up to here can simply be orphaned if we abort
 
214
    ## the commit; it will leave junk files behind but that doesn't
 
215
    ## matter.
 
216
 
 
217
    ## TODO: Read back the just-generated changeset, and make sure it
 
218
    ## applies and recreates the right state.
 
219
 
 
220
    ## TODO: Also calculate and store the inventory SHA1
 
221
    mutter("committing patch r%d" % (branch.revno() + 1))
 
222
 
 
223
    branch.append_revision(rev_id)
 
224
 
 
225
    if verbose:
 
226
        note("commited r%d" % branch.revno())
230
227
 
231
228
 
232
229