anchor.diff:    }
   
     /**
  +   * Calls the [func] with given [args] and [namedArgs] which returns a future.
  +   * On completion checks and returns a gir_clone_cancel exception if the
  +   * operation was cancelled. The caller must catch the exception and do the
  +   * necessary cleanup.
  +   */
  +  Future callMethod(Function func, List args, [Map<Symbol, dynamic> namedArgs]) {
  +    return Function.apply(func, args, namedArgs).then((result) {
  +      cancel.check();
  +      return result;
  +    });
  +  }
  +
  +  /**
      * Public for testing purpose.
      */
     Future startClone(HttpFetcher fetcher) {
       return _checkDirectory(_options.root, _options.store, true).then((_) {
         return _options.root.createDirectory(".git").then(
             (chrome.DirectoryEntry gitDir) {
  -        return fetcher.fetchUploadRefs().then((List<GitRef> refs) {
  +        return callMethod(fetcher.fetchUploadRefs,[]).then((List<GitRef> refs) {
             logger.info(_stopwatch.finishCurrentTask('fetchUploadRefs'));
   
             if (refs.isEmpty) {
  
positive.code: 
            return gitDir.createDirectory('objects').then(
                (chrome.DirectoryEntry objectsDir) {
              return _createPackFiles(objectsDir, packName, packData,
                  packIdxData).then((_) {
                logger.info(_stopwatch.finishCurrentTask('createPackFiles'));
                PackIndex packIdx = new PackIndex(packIdxData);
                Pack pack = new Pack(packData, _options.store);
  
negative.code:     if (_options.progressCallback == null) {
        _options.progressCallback = nopFunction;
      }
  
      cancel = new CloneCancel();
    }
  
    chrome.DirectoryEntry get root => _options.root;
  