'Begins the transaction, returning a list of files that need uploading.
All calls to AddFile must be made before calling Begin().
Returns:
A list of pathnames for files that should be uploaded using UploadFile()
before Commit() can be called.'

def Begin(self):

    assert (not self.in_transaction), 'Already    in    a    transaction.'
    config_copy = copy.deepcopy(self.config)
    for url in config_copy.handlers:
        handler_type = url.GetHandlerType()
        if url.application_readable:
            if (handler_type == 'static_dir'):
                url.static_dir = ('%s/%s' % (STATIC_FILE_PREFIX, url.static_dir))
            elif (handler_type == 'static_files'):
                url.static_files = ('%s/%s' % (STATIC_FILE_PREFIX, url.static_files))
                url.upload = ('%s/%s' % (STATIC_FILE_PREFIX, url.upload))
    response = self.logging_context.Send('/api/appversion/create', payload=config_copy.ToYAML())
    result = self._ValidateBeginYaml(response)
    if result:
        warnings = result.get('warnings')
        for warning in warnings:
            StatusUpdate(('WARNING:    %s' % warning), self.error_fh)
    self.in_transaction = True
    files_to_clone = []
    blobs_to_clone = []
    errorblobs = {}
    for (path, content_hash) in self.files.iteritems():
        file_classification = FileClassification(self.config, path, error_fh=self.error_fh)
        if file_classification.IsStaticFile():
            upload_path = path
            if file_classification.IsApplicationFile():
                upload_path = ('%s/%s' % (STATIC_FILE_PREFIX, path))
            blobs_to_clone.append((path, upload_path, content_hash, file_classification.StaticMimeType()))
        if file_classification.IsErrorFile():
            errorblobs[path] = content_hash
        if file_classification.IsApplicationFile():
            files_to_clone.append((path, path, content_hash))
    files_to_upload = {}
    def CloneFiles(url, files, file_type):
        'Sends    files    to    the    given    url.\n\n                        Args:\n                                url:    the    server    URL    to    use.\n                                files:    a    list    of    files\n                                file_type:    the    type    of    the    files\n                        '
        if (not files):
            return
        StatusUpdate(('Cloning    %d    %s    file%s.' % (len(files), file_type, (((len(files) != 1) and 's') or ''))), self.error_fh)
        max_files = self.resource_limits['max_files_to_clone']
        for i in xrange(0, len(files), max_files):
            if ((i > 0) and ((i % max_files) == 0)):
                StatusUpdate(('Cloned    %d    files.' % i), self.error_fh)
            chunk = files[i:min(len(files), (i + max_files))]
            result = self.logging_context.Send(url, payload=BuildClonePostBody(chunk))
            if result:
                to_upload = {}
                for f in result.split(LIST_DELIMITER):
                    for entry in files:
                        (real_path, upload_path) = entry[:2]
                        if (f == upload_path):
                            to_upload[real_path] = self.files[real_path]
                            break
                files_to_upload.update(to_upload)
    CloneFiles('/api/appversion/cloneblobs', blobs_to_clone, 'static')
    CloneFiles('/api/appversion/clonefiles', files_to_clone, 'application')
    logging.debug('Files    to    upload:    %s', files_to_upload)
    for (path, content_hash) in errorblobs.iteritems():
        files_to_upload[path] = content_hash
    self.files = files_to_upload
    return sorted(files_to_upload.iterkeys())
