Example usage for org.eclipse.jgit.merge MergeStrategy RECURSIVE

List of usage examples for org.eclipse.jgit.merge MergeStrategy RECURSIVE

Introduction

In this page you can find the example usage for org.eclipse.jgit.merge MergeStrategy RECURSIVE.

Prototype

ThreeWayMergeStrategy RECURSIVE

To view the source code for org.eclipse.jgit.merge MergeStrategy RECURSIVE.

Click Source Link

Document

Recursive strategy to merge paths.

Usage

From source file:br.com.riselabs.cotonet.builder.NetworkBuilder.java

License:Open Source License

/**
 * Returns the conflicting merge scenarios
 * /*from   ww w.j a v  a  2 s  . com*/
 * @return - a list of merge scenarios. it may be empty in case of no
 *         conflict.
 * @throws IOException
 */
private List<MergeScenario> getMergeScenarios() throws IOException {
    List<MergeScenario> result = new ArrayList<MergeScenario>();
    List<RevCommit> mergeCommits = new ArrayList<RevCommit>();
    Iterable<RevCommit> gitlog;
    try {
        Git git = Git.wrap(getProject().getRepository());
        gitlog = git.log().call();
        for (RevCommit commit : gitlog) {
            if (commit.getParentCount() == 2) {
                mergeCommits.add(commit);
                // collecting merge commits
                // we know there is only to parents
                RevCommit leftParent = commit.getParent(0);
                RevCommit rightParent = commit.getParent(1);
                ThreeWayMerger merger = MergeStrategy.RECURSIVE.newMerger(getProject().getRepository(), true);
                // selecting the conflicting ones
                boolean noConflicts = false;
                try {
                    noConflicts = merger.merge(leftParent, rightParent);
                } catch (NoMergeBaseException e) {
                    StringBuilder sb = new StringBuilder();
                    sb.append("[" + project.getName() + ":" + project.getUrl() + "] "
                            + "Skipping merge scenario due to '" + e.getMessage() + "'\n");
                    sb.append("---> Skipped scenario:\n");
                    sb.append("::Base (<several>): \n");
                    sb.append("::Left (" + leftParent.getAuthorIdent().getWhen().toString() + "):"
                            + leftParent.getName() + "\n");
                    sb.append("::Right (" + rightParent.getAuthorIdent().getWhen().toString() + "):"
                            + rightParent.getName() + "\n");
                    Logger.log(log, sb.toString());
                    Logger.logStackTrace(log, e);
                    continue;
                }
                if (noConflicts) {
                    continue;
                }
                RevWalk walk = new RevWalk(getProject().getRepository());
                // for merges without a base commit
                if (merger.getBaseCommitId() == null)
                    continue;
                RevCommit baseCommit = walk.lookupCommit(merger.getBaseCommitId());
                walk.close();

                Timestamp mergeDate = new Timestamp(commit.getAuthorIdent().getWhen().getTime());
                result.add(new MergeScenario(baseCommit, leftParent, rightParent, commit, mergeDate));
            }
        }
    } catch (GitAPIException e) {
        Logger.logStackTrace(log, e);
    }
    return result;
}

From source file:br.com.riselabs.cotonet.builder.NetworkBuilder.java

License:Open Source License

/**
 * Returns the conflicting files of the given scenario.
 * /* w  w  w .  j  av  a2  s.co  m*/
 * @param scenario
 * @return
 * @throws CheckoutConflictException
 * @throws GitAPIException
 */
private List<File> getConflictingFiles(MergeScenario scenario)
        throws CheckoutConflictException, GitAPIException {
    Git git = Git.wrap(getProject().getRepository());
    // this is for the cases of restarting after exception in a conflict
    // scenario analysis
    try {
        git.reset().setRef(scenario.getLeft().getName()).setMode(ResetType.HARD).call();
    } catch (JGitInternalException e) {
        Logger.log(log, "[" + project.getName() + "] JGit Reset Command ended with exception."
                + " Trying external reset command.");
        ExternalGitCommand egit = new ExternalGitCommand();
        try {
            egit.setType(CommandType.RESET).setDirectory(project.getRepository().getDirectory().getParentFile())
                    .call();
        } catch (BlameException e1) {
            Logger.logStackTrace(log, e1);
            return null;
        }
    }

    CheckoutCommand ckoutCmd = git.checkout();
    ckoutCmd.setName(scenario.getLeft().getName());
    ckoutCmd.setStartPoint(scenario.getLeft());
    ckoutCmd.call();

    MergeCommand mergeCmd = git.merge();
    mergeCmd.setCommit(false);
    mergeCmd.setStrategy(MergeStrategy.RECURSIVE);
    mergeCmd.include(scenario.getRight());

    Set<String> conflictingPaths;
    try {
        // dealing with MissingObjectException
        MergeResult mResult = mergeCmd.call();
        // dealing with Ghosts conflicts
        conflictingPaths = mResult.getConflicts().keySet();
    } catch (NullPointerException | JGitInternalException e) {
        StringBuilder sb = new StringBuilder();
        sb.append("[" + project.getName() + ":" + project.getUrl() + "] " + "Skipping merge scenario due to '"
                + e.getMessage() + "'\n");
        sb.append("--> Exception: " + e.getClass());
        sb.append("--> Skipped scenario:\n");
        sb.append("::Base:" + scenario.getBase().getName() + "\n");
        sb.append("::Left:" + scenario.getLeft().getName() + "\n");
        sb.append("::Right:" + scenario.getRight().getName() + "\n");
        Logger.log(log, sb.toString());
        return null;
    }
    List<File> result = new ArrayList<File>();
    for (String path : conflictingPaths) {
        result.add(new File(getProject().getRepository().getDirectory().getParent(), path));
    }
    return result;
}

From source file:br.com.riselabs.cotonet.test.helpers.RepositoryTestCaseTest.java

License:Open Source License

@Test
public void mergeConflictScenarioInMemoryRepository() throws Exception {
    MergeScenario ms = setCollaborationScenarioInBareRepository();

    MergeResult result = git.merge().setStrategy(MergeStrategy.RECURSIVE).include("side", ms.getRight()).call();
    assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
}

From source file:ch.sbb.releasetrain.git.GitRepoImpl.java

License:Apache License

private Git pull(Git git) throws GitAPIException {
    if (remoteBranchExists(git)) {
        PullResult result = git.pull().setStrategy(MergeStrategy.RECURSIVE)
                .setCredentialsProvider(this.credentialsProvider()).call();
        if (result.isSuccessful()) {
            return git;
        } else {//  ww w  .j  a  v  a 2s.c o  m
            log.info(
                    "*** pulling git, not able to merge with MergeStrategy.RECURSIVE go for MergeStrategy.THEIRS");
            result = git.pull().setStrategy(MergeStrategy.THEIRS)
                    .setCredentialsProvider(this.credentialsProvider()).call();
            if (result.isSuccessful()) {
                return git;
            }
            throw new GitException("Pull failed: " + result.toString());
        }
    } else {
        return git;
    }
}

From source file:com.door43.translationstudio.ui.dialogs.BackupDialog.java

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
    v = inflater.inflate(R.layout.dialog_backup, container, false);

    // get target translation to backup
    Bundle args = getArguments();//from  www.  j  a v  a 2  s .  c o m
    if (args != null && args.containsKey(ARG_TARGET_TRANSLATION_ID)) {
        String targetTranslationId = args.getString(ARG_TARGET_TRANSLATION_ID, null);
        targetTranslation = App.getTranslator().getTargetTranslation(targetTranslationId);
        if (targetTranslation == null) {
            throw new InvalidParameterException(
                    "The target translation '" + targetTranslationId + "' is invalid");
        }
    } else {
        throw new InvalidParameterException("The target translation id was not specified");
    }

    targetTranslation.setDefaultContributor(App.getProfile().getNativeSpeaker());

    mBackupToCloudButton = (LinearLayout) v.findViewById(R.id.backup_to_cloud);
    LinearLayout exportProjectButton = (LinearLayout) v.findViewById(R.id.backup_to_sd);
    Button backupToAppButton = (Button) v.findViewById(R.id.backup_to_app);
    Button backupToDeviceButton = (Button) v.findViewById(R.id.backup_to_device);
    LinearLayout exportToPDFButton = (LinearLayout) v.findViewById(R.id.export_to_pdf);
    LinearLayout exportToUsfmButton = (LinearLayout) v.findViewById(R.id.export_to_usfm);

    Button logout = (Button) v.findViewById(R.id.logout_button);
    logout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            App.setProfile(null);
            Intent logoutIntent = new Intent(getActivity(), ProfileActivity.class);
            startActivity(logoutIntent);
        }
    });

    final String filename = targetTranslation.getId() + "." + Translator.ARCHIVE_EXTENSION;

    initProgressWatcher(R.string.backup);

    if (savedInstanceState != null) {
        // check if returning from device alias dialog
        settingDeviceAlias = savedInstanceState.getBoolean(STATE_SETTING_DEVICE_ALIAS, false);
        mDialogShown = eDialogShown
                .fromInt(savedInstanceState.getInt(STATE_DIALOG_SHOWN, eDialogShown.NONE.getValue()));
        mAccessFile = savedInstanceState.getString(STATE_ACCESS_FILE, null);
        mDialogMessage = savedInstanceState.getString(STATE_DIALOG_MESSAGE, null);
        isOutputToDocumentFile = savedInstanceState.getBoolean(STATE_OUTPUT_TO_DOCUMENT_FILE, false);
        mDestinationFolderUri = Uri.parse(savedInstanceState.getString(STATE_OUTPUT_FOLDER_URI, ""));
        restoreDialogs();
    }

    Button dismissButton = (Button) v.findViewById(R.id.dismiss_button);
    dismissButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dismiss();
        }
    });

    backupToDeviceButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO: 11/18/2015 eventually we need to support bluetooth as well as an adhoc network
            showDeviceNetworkAliasDialog();
        }
    });

    // backup buttons
    mBackupToCloudButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (App.isNetworkAvailable()) {
                // make sure we have a gogs user
                if (App.getProfile().gogsUser == null) {
                    showDoor43LoginDialog();
                    return;
                }

                doPullTargetTranslationTask(targetTranslation, MergeStrategy.RECURSIVE);
            } else {
                showNoInternetDialog(); // replaced snack popup which could be hidden behind dialog
            }
        }
    });

    exportToPDFButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            PrintDialog printDialog = new PrintDialog();
            Bundle printArgs = new Bundle();
            printArgs.putString(PrintDialog.ARG_TARGET_TRANSLATION_ID, targetTranslation.getId());
            printDialog.setArguments(printArgs);
            showDialogFragment(printDialog, PrintDialog.TAG);
        }
    });

    exportProjectButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doSelectDestinationFolder(false);
        }
    });

    exportToUsfmButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doSelectDestinationFolder(true);
        }
    });

    if (targetTranslation.isObsProject()) {
        LinearLayout exportToUsfmSeparator = (LinearLayout) v.findViewById(R.id.export_to_usfm_separator);
        exportToUsfmSeparator.setVisibility(View.GONE);
        exportToUsfmButton.setVisibility(View.GONE);
    }

    backupToAppButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            File exportFile = new File(App.getSharingDir(), filename);
            try {
                App.getTranslator().exportArchive(targetTranslation, exportFile);
            } catch (Exception e) {
                Logger.e(TAG, "Failed to export the target translation " + targetTranslation.getId(), e);
            }
            if (exportFile.exists()) {
                Uri u = FileProvider.getUriForFile(getActivity(), "com.door43.translationstudio.fileprovider",
                        exportFile);
                Intent i = new Intent(Intent.ACTION_SEND);
                i.setType("application/zip");
                i.putExtra(Intent.EXTRA_STREAM, u);
                startActivity(Intent.createChooser(i, "Email:"));
            } else {
                Snackbar snack = Snackbar.make(getActivity().findViewById(android.R.id.content),
                        R.string.translation_export_failed, Snackbar.LENGTH_LONG);
                ViewUtil.setSnackBarTextColor(snack, getResources().getColor(R.color.light_primary_text));
                snack.show();
            }
        }
    });

    // connect to existing tasks
    PullTargetTranslationTask pullTask = (PullTargetTranslationTask) TaskManager
            .getTask(PullTargetTranslationTask.TASK_ID);
    RegisterSSHKeysTask keysTask = (RegisterSSHKeysTask) TaskManager.getTask(RegisterSSHKeysTask.TASK_ID);
    CreateRepositoryTask repoTask = (CreateRepositoryTask) TaskManager.getTask(CreateRepositoryTask.TASK_ID);
    PushTargetTranslationTask pushTask = (PushTargetTranslationTask) TaskManager
            .getTask(PushTargetTranslationTask.TASK_ID);
    ExportProjectTask projectExportTask = (ExportProjectTask) TaskManager.getTask(ExportProjectTask.TASK_ID);
    ExportToUsfmTask usfmExportTask = (ExportToUsfmTask) TaskManager.getTask(ExportToUsfmTask.TASK_ID);

    if (pullTask != null) {
        taskWatcher.watch(pullTask);
    } else if (keysTask != null) {
        taskWatcher.watch(keysTask);
    } else if (repoTask != null) {
        taskWatcher.watch(repoTask);
    } else if (pushTask != null) {
        taskWatcher.watch(pushTask);
    } else if (projectExportTask != null) {
        taskWatcher.watch(projectExportTask);
    } else if (usfmExportTask != null) {
        taskWatcher.watch(usfmExportTask);
    }

    return v;
}

From source file:com.door43.translationstudio.ui.dialogs.BackupDialog.java

@Override
public void onFinished(ManagedTask task) {
    taskWatcher.stop();// w  w  w .j a  v a2  s. com
    if (task instanceof PullTargetTranslationTask) {
        PullTargetTranslationTask pullTask = (PullTargetTranslationTask) task;
        //            mRemoteURL = pullTask.getSourceURL();
        PullTargetTranslationTask.Status status = pullTask.getStatus();
        //  TRICKY: we continue to push for unknown status in case the repo was just created (the missing branch is an error)
        // the pull task will catch any errors
        if (status == PullTargetTranslationTask.Status.UP_TO_DATE
                || status == PullTargetTranslationTask.Status.UNKNOWN) {
            Logger.i(this.getClass().getName(),
                    "Changes on the server were synced with " + targetTranslation.getId());

            initProgressWatcher(R.string.backup);
            PushTargetTranslationTask pushtask = new PushTargetTranslationTask(targetTranslation);
            taskWatcher.watch(pushtask);
            TaskManager.addTask(pushtask, PushTargetTranslationTask.TASK_ID);
        } else if (status == PullTargetTranslationTask.Status.AUTH_FAILURE) {
            Logger.i(this.getClass().getName(), "Authentication failed");
            // if we have already tried ask the user if they would like to try again
            if (App.hasSSHKeys()) {
                showAuthFailure();
                return;
            }

            initProgressWatcher(R.string.backup);
            RegisterSSHKeysTask keyTask = new RegisterSSHKeysTask(false);
            taskWatcher.watch(keyTask);
            TaskManager.addTask(keyTask, RegisterSSHKeysTask.TASK_ID);
        } else if (status == PullTargetTranslationTask.Status.NO_REMOTE_REPO) {
            Logger.i(this.getClass().getName(),
                    "The repository " + targetTranslation.getId() + " could not be found");
            // create missing repo
            initProgressWatcher(R.string.backup);
            CreateRepositoryTask repoTask = new CreateRepositoryTask(targetTranslation);
            taskWatcher.watch(repoTask);
            TaskManager.addTask(repoTask, CreateRepositoryTask.TASK_ID);
        } else if (status == PullTargetTranslationTask.Status.MERGE_CONFLICTS) {
            Logger.i(this.getClass().getName(),
                    "The server contains conflicting changes for " + targetTranslation.getId());
            MergeConflictsHandler.backgroundTestForConflictedChunks(targetTranslation.getId(),
                    new MergeConflictsHandler.OnMergeConflictListener() {
                        @Override
                        public void onNoMergeConflict(String targetTranslationId) {
                            // probably the manifest or license gave a false positive
                            Logger.i(this.getClass().getName(),
                                    "Changes on the server were synced with " + targetTranslation.getId());

                            initProgressWatcher(R.string.backup);
                            PushTargetTranslationTask pushtask = new PushTargetTranslationTask(
                                    targetTranslation);
                            taskWatcher.watch(pushtask);
                            TaskManager.addTask(pushtask, PushTargetTranslationTask.TASK_ID);
                        }

                        @Override
                        public void onMergeConflict(String targetTranslationId) {
                            showMergeConflict(targetTranslation);
                        }
                    });
        } else {
            notifyBackupFailed(targetTranslation);
        }
    } else if (task instanceof RegisterSSHKeysTask) {
        if (((RegisterSSHKeysTask) task).isSuccess()) {
            Logger.i(this.getClass().getName(), "SSH keys were registered with the server");
            // try to push again
            doPullTargetTranslationTask(targetTranslation, MergeStrategy.RECURSIVE);
        } else {
            notifyBackupFailed(targetTranslation);
        }
    } else if (task instanceof CreateRepositoryTask) {
        if (((CreateRepositoryTask) task).isSuccess()) {
            Logger.i(this.getClass().getName(),
                    "A new repository " + targetTranslation.getId() + " was created on the server");
            doPullTargetTranslationTask(targetTranslation, MergeStrategy.RECURSIVE);
        } else {
            notifyBackupFailed(targetTranslation);
        }
    } else if (task instanceof PushTargetTranslationTask) {
        PushTargetTranslationTask.Status status = ((PushTargetTranslationTask) task).getStatus();
        final String message = ((PushTargetTranslationTask) task).getMessage();

        if (status == PushTargetTranslationTask.Status.OK) {
            Logger.i(this.getClass().getName(),
                    "The target translation " + targetTranslation.getId() + " was pushed to the server");
            showPushSuccess(message);
        } else if (status.isRejected()) {
            Logger.i(this.getClass().getName(), "Push Rejected");
            showPushRejection(targetTranslation);
        } else if (status == PushTargetTranslationTask.Status.AUTH_FAILURE) {
            Logger.i(this.getClass().getName(), "Authentication failed");
            showAuthFailure();
        } else {
            notifyBackupFailed(targetTranslation);
        }
    } else if (task instanceof ExportProjectTask) {
        ExportProjectTask projectExportTask = (ExportProjectTask) task;
        ExportProjectTask.ExportResults results = (ExportProjectTask.ExportResults) projectExportTask
                .getResult();

        Logger.i(TAG, "Project export success = " + results.success);
        if (results.success) {
            showBackupResults(R.string.backup_success, results.filePath);
        } else {
            showBackupResults(R.string.backup_failed, results.filePath);
        }
    } else if (task instanceof ExportToUsfmTask) {
        ExportToUsfmTask usfmExportTask = (ExportToUsfmTask) task;
        Uri exportFile = (Uri) usfmExportTask.getResult();
        boolean success = (exportFile != null);

        String message;
        if (success) {
            String format = getResources().getString(R.string.export_success);
            message = String.format(format, SdUtils.getPathString(exportFile.toString()));
        } else {
            message = getResources().getString(R.string.export_failed);
        }

        showUsfmExportResults(message);
    }
}

From source file:com.gitblit.utils.JGitUtils.java

License:Apache License

public static boolean commitIndex(Repository db, String branch, DirCache index, ObjectId parentId,
        boolean forceCommit, String author, String authorEmail, String message)
        throws IOException, ConcurrentRefUpdateException {
    boolean success = false;

    ObjectId headId = db.resolve(branch + "^{commit}");
    ObjectId baseId = parentId;/*from   w  w w .j  a v  a 2  s  . c  om*/
    if (baseId == null || headId == null) {
        return false;
    }

    ObjectInserter odi = db.newObjectInserter();
    try {
        // Create the in-memory index of the new/updated ticket
        ObjectId indexTreeId = index.writeTree(odi);

        // Create a commit object
        PersonIdent ident = new PersonIdent(author, authorEmail);

        if (forceCommit == false) {
            ThreeWayMerger merger = MergeStrategy.RECURSIVE.newMerger(db, true);
            merger.setObjectInserter(odi);
            merger.setBase(baseId);
            boolean mergeSuccess = merger.merge(indexTreeId, headId);

            if (mergeSuccess) {
                indexTreeId = merger.getResultTreeId();
            } else {
                //Manual merge required
                return false;
            }
        }

        CommitBuilder commit = new CommitBuilder();
        commit.setAuthor(ident);
        commit.setCommitter(ident);
        commit.setEncoding(com.gitblit.Constants.ENCODING);
        commit.setMessage(message);
        commit.setParentId(headId);
        commit.setTreeId(indexTreeId);

        // Insert the commit into the repository
        ObjectId commitId = odi.insert(commit);
        odi.flush();

        RevWalk revWalk = new RevWalk(db);
        try {
            RevCommit revCommit = revWalk.parseCommit(commitId);
            RefUpdate ru = db.updateRef(branch);
            ru.setForceUpdate(forceCommit);
            ru.setNewObjectId(commitId);
            ru.setExpectedOldObjectId(headId);
            ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
            Result rc = ru.update();

            switch (rc) {
            case NEW:
            case FORCED:
            case FAST_FORWARD:
                success = true;
                break;
            case REJECTED:
            case LOCK_FAILURE:
                throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
            default:
                throw new JGitInternalException(MessageFormat.format(JGitText.get().updatingRefFailed, branch,
                        commitId.toString(), rc));
            }
        } finally {
            revWalk.close();
        }
    } finally {
        odi.close();
    }
    return success;
}

From source file:com.google.gerrit.server.git.MergeUtil.java

License:Apache License

public static ThreeWayMergeStrategy getMergeStrategy(Config cfg) {
    return useRecursiveMerge(cfg) ? MergeStrategy.RECURSIVE : MergeStrategy.RESOLVE;
}

From source file:com.google.gerrit.server.git.MergeUtil.java

License:Apache License

public static String mergeStrategyName(boolean useContentMerge, boolean useRecursiveMerge) {
    if (useContentMerge) {
        // Settings for this project allow us to try and automatically resolve
        // conflicts within files if needed. Use either the old resolve merger or
        // new recursive merger, and instruct to operate in core.
        if (useRecursiveMerge) {
            return MergeStrategy.RECURSIVE.getName();
        } else {//from  w w  w . j av a  2 s.  c o m
            return MergeStrategy.RESOLVE.getName();
        }
    } else {
        // No auto conflict resolving allowed. If any of the
        // affected files was modified, merge will fail.
        return MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.getName();
    }
}

From source file:jetbrains.buildServer.buildTriggers.vcs.git.GitMergeSupport.java

License:Apache License

@NotNull
public Map<MergeTask, MergeResult> tryMerge(@NotNull VcsRoot root, @NotNull List<MergeTask> tasks,
        @NotNull MergeOptions options) throws VcsException {
    Map<MergeTask, MergeResult> mergeResults = new HashMap<MergeTask, MergeResult>();
    OperationContext context = myVcs.createContext(root, "merge");
    try {//  w  ww.j  av a2s.  c om
        Repository db = context.getRepository();
        for (MergeTask t : tasks) {
            ObjectId src = ObjectId.fromString(t.getSourceRevision());
            ObjectId dst = ObjectId.fromString(t.getDestinationRevision());
            ResolveMerger merger = (ResolveMerger) MergeStrategy.RECURSIVE.newMerger(db, true);
            try {
                boolean success = merger.merge(dst, src);
                if (success) {
                    mergeResults.put(t, MergeResult.createMergeSuccessResult());
                } else {
                    mergeResults.put(t, MergeResult.createMergeError(merger.getUnmergedPaths()));
                }
            } catch (IOException mergeException) {
                mergeResults.put(t, MergeResult.createMergeError(mergeException.getMessage()));
            }
        }
    } catch (Exception e) {
        throw context.wrapException(e);
    } finally {
        context.close();
    }
    return mergeResults;
}