Bitbucket 7.14 introduces a new WorkTree API to create commits and make other changes to a Repository
. App developers
are strongly encouraged to start developing against this API and offer feedback related to their experience and use cases.
This helps the team ensure the new API is as robust and capable as possible, since it will be the only option from 8.0.
Following is an example that demonstrates one such use case where you will create a commit on a new branch in a repository.
Assume that the repository in which you shall be performing these changes is available in a variable called repository
.
Use GitWorkTreeBuilderFactory
to create a GitWorkTreeBuilder
and pass a commit hash that must be
checked out in the worktree. You can initialize the resulting GitWorkTree
by doing a checkout in one of two ways:
SPARSE
, which (effectively) randomly selects a small number of files (generally 1) to actually check out while
not checking out the others. This results in a nearly-empty worktree on disk, where git status
shows no changes.
Commands like git cherry-pick
and git rebase
can be used in this type of checkout.
NONE
, which essentially is git clone --no-checkout
followed by git reset
to unstage the deletions. This
results in a worktree that is empty on disk, but where git status
shows every file as deleted. Commands like
git merge
run fine in this sort of worktree, but others like git cherry-pick
and git rebase
cannot be used.
Absence of the option to do a "full" checkout is by design and is for scalability reasons. In this example, you will
be using the NONE
checkout type. You will later use the builder to create a commit and publish it to a new branch
in the repository.
1 2GitWorkTreeBuilder builder = workTreeBuilderFactory.builder(repository) .commit("6053a1eaa1c009dd11092d09a72f3c41af1b59ad") .checkoutType(GitCheckoutType.NONE);
GitWorkTreeBuilder
:1 2builder.execute(workTree -> { // Merge in a commit from master workTree.builder().merge() .normal() .author(new SimplePerson("committer-name", "committer@email.com")) .message("Test merge") .commit("2d8897c9ac29ce42c3442cf80ac977057045e7f6") .build() .call(); // Add a new file in a directory and create a commit workTree.mkdir("new-directory"); workTree.write("new-directory/some-file.txt", UTF_8, writer -> writer.write("This is a new file\n")); workTree.builder().add() .path("new-directory/some-file.txt") .build() .call(); workTree.builder().commit() .author(new SimplePerson("committer-name", "committer@email.com")) .message("Testing the work tree API") .build() .call(); });
GitWorkTree
back to repository
, you will need a GitWorkTreeRepositoryHookInvoker
.
There's a convenience implementation, AbstractGitWorkTreeRepositoryHookInvoker
that you can use as the base for your implementation.1 2class SimpleHookInvoker extends AbstractGitWorkTreeRepositoryHookInvoker<RepositoryHookRequest> { private RefChange refChange; SimpleHookInvoker(@Nonnull EventPublisher eventPublisher, @Nonnull RepositoryHookService repositoryHookService) { super(eventPublisher, repositoryHookService); } @Nonnull RefChange getRefChange() { return refChange; } @Nonnull @Override protected RepositoryHookRequest createHookRequest(@Nonnull GitWorkTree workTree, @Nonnull List<RefChange> refChanges) { return new SimpleRepositoryHookRequest.Builder(workTree.getRepository(), FILE_EDIT) .refChanges(refChanges) .build(); } @Nonnull @Override protected ApplicationEvent createPostUpdateEvent(@Nonnull RepositoryHookRequest request) { refChange = request.getRefChanges().stream().findFirst().orElse(null); return new AbstractRepositoryRefsChangedEvent(this, request.getRepository(), request.getRefChanges()) { }; } }
GitWorkTreeRepositoryHookInvoker
, you can now publish changes you made to the
temporary WorkTree
back to repository
. Change the builder.execute()
call in Step 2 to include the publishing
step now. Here is what the completed version looks like:1 2RefChange refChange = builder.execute(workTree -> { // Merge in a commit from master workTree.builder().merge() .normal() .author(new SimplePerson("committer-name", "committer@email.com")) .message("Master merge") .commit("2d8897c9ac29ce42c3442cf80ac977057045e7f6") .build() .call(); // Add a new file in a directory and create a commit workTree.mkdir("new-directory"); workTree.write("new-directory/some-file.txt", UTF_8, writer -> writer.write("This is a new file\n")); workTree.builder().add() .path("new-directory/some-file.txt") .build() .call(); workTree.builder().commit() .author(new SimplePerson("committer-name", "committer@email.com")) .message("Testing the work tree API") .build() .call(); // Publish changes in the temporary worktree back to our repository on a new branch HookInvoker invoker = new SimpleHookInvoker(eventPublisher, repositoryHookService); workTree.publish(new PublishGitWorkTreeParameters.Builder(invoker) .author(new SimplePerson("committer-name", "committer@email.com")) .branch("new-branch", "6053a1eaa1c009dd11092d09a72f3c41af1b59ad") .build()); return invoker.getRefChange(); });
The resulting RefChange
object now contains details of the update you just made.
Rate this page: