use of org.craftercms.studio.api.v1.constant.StudioConstants.PATTERN_SITE in project studio by craftercms.
the class RepositoryManagementServiceInternalImpl method resolveConflict.
@Override
public boolean resolveConflict(String siteId, String path, String resolution) throws CryptoException, ServiceLayerException {
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
Repository repo = helper.getRepository(siteId, SANDBOX);
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, siteId);
generalLockService.lock(gitLockKey);
try (Git git = new Git(repo)) {
ResetCommand resetCommand;
CheckoutCommand checkoutCommand;
switch(resolution.toLowerCase()) {
case "ours":
logger.debug("Resolve conflict using OURS strategy for site " + siteId + " and path " + path);
logger.debug("Reset merge conflict in git index");
resetCommand = git.reset().addPath(helper.getGitPath(path));
retryingRepositoryOperationFacade.call(resetCommand);
logger.debug("Checkout content from HEAD of studio repository");
checkoutCommand = git.checkout().addPath(helper.getGitPath(path)).setStartPoint(Constants.HEAD);
retryingRepositoryOperationFacade.call(checkoutCommand);
break;
case "theirs":
logger.debug("Resolve conflict using THEIRS strategy for site " + siteId + " and path " + path);
logger.debug("Reset merge conflict in git index");
resetCommand = git.reset().addPath(helper.getGitPath(path));
retryingRepositoryOperationFacade.call(resetCommand);
logger.debug("Checkout content from merge HEAD of remote repository");
List<ObjectId> mergeHeads = repo.readMergeHeads();
ObjectId mergeCommitId = mergeHeads.get(0);
checkoutCommand = git.checkout().addPath(helper.getGitPath(path)).setStartPoint(mergeCommitId.getName());
retryingRepositoryOperationFacade.call(checkoutCommand);
break;
default:
throw new ServiceLayerException("Unsupported resolution strategy for repository conflicts");
}
if (repo.getRepositoryState() == RepositoryState.MERGING_RESOLVED) {
logger.debug("Merge resolved. Check if there are no uncommitted changes (repo is clean)");
Status status = git.status().call();
if (!status.hasUncommittedChanges()) {
logger.debug("Repository is clean. Committing to complete merge");
String userName = securityService.getCurrentUser();
User user = userServiceInternal.getUserByIdOrUsername(-1, userName);
PersonIdent personIdent = helper.getAuthorIdent(user);
CommitCommand commitCommand = git.commit().setAllowEmpty(true).setMessage("Merge resolved. Repo is clean (no changes)").setAuthor(personIdent);
retryingRepositoryOperationFacade.call(commitCommand);
}
}
} catch (GitAPIException | IOException | UserNotFoundException | ServiceLayerException e) {
logger.error("Error while resolving conflict for site " + siteId + " using " + resolution + " resolution " + "strategy", e);
throw new ServiceLayerException("Error while resolving conflict for site " + siteId + " using " + resolution + " resolution " + "strategy", e);
} finally {
generalLockService.unlock(gitLockKey);
}
return true;
}
use of org.craftercms.studio.api.v1.constant.StudioConstants.PATTERN_SITE in project studio by craftercms.
the class RepositoryManagementServiceInternalImpl method commitResolution.
@Override
public boolean commitResolution(String siteId, String commitMessage) throws CryptoException, ServiceLayerException {
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
Repository repo = helper.getRepository(siteId, SANDBOX);
logger.debug("Commit resolution for merge conflict for site " + siteId);
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, siteId);
generalLockService.lock(gitLockKey);
try (Git git = new Git(repo)) {
Status status = git.status().call();
logger.debug("Add all uncommitted changes/files");
AddCommand addCommand = git.add();
for (String uncommited : status.getUncommittedChanges()) {
addCommand.addFilepattern(uncommited);
}
retryingRepositoryOperationFacade.call(addCommand);
logger.debug("Commit changes");
CommitCommand commitCommand = git.commit();
String userName = securityService.getCurrentUser();
User user = userServiceInternal.getUserByIdOrUsername(-1, userName);
PersonIdent personIdent = helper.getAuthorIdent(user);
String prologue = studioConfiguration.getProperty(REPO_COMMIT_MESSAGE_PROLOGUE);
String postscript = studioConfiguration.getProperty(REPO_COMMIT_MESSAGE_POSTSCRIPT);
StringBuilder sbMessage = new StringBuilder();
if (StringUtils.isNotEmpty(prologue)) {
sbMessage.append(prologue).append("\n\n");
}
sbMessage.append(commitMessage);
if (StringUtils.isNotEmpty(postscript)) {
sbMessage.append("\n\n").append(postscript);
}
commitCommand.setCommitter(personIdent).setAuthor(personIdent).setMessage(sbMessage.toString());
retryingRepositoryOperationFacade.call(commitCommand);
return true;
} catch (GitAPIException | UserNotFoundException | ServiceLayerException e) {
logger.error("Error while committing conflict resolution for site " + siteId, e);
throw new ServiceLayerException("Error while committing conflict resolution for site " + siteId, e);
} finally {
generalLockService.unlock(gitLockKey);
}
}
use of org.craftercms.studio.api.v1.constant.StudioConstants.PATTERN_SITE in project studio by craftercms.
the class RepositoryManagementServiceInternalImpl method cancelFailedPull.
@Override
public boolean cancelFailedPull(String siteId) throws ServiceLayerException, CryptoException {
logger.debug("To cancel failed pull, reset hard needs to be executed");
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
Repository repo = helper.getRepository(siteId, SANDBOX);
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, siteId);
generalLockService.lock(gitLockKey);
try (Git git = new Git(repo)) {
ResetCommand resetCommand = git.reset().setMode(ResetCommand.ResetType.HARD);
retryingRepositoryOperationFacade.call(resetCommand);
} catch (GitAPIException e) {
logger.error("Error while canceling failed pull for site " + siteId, e);
throw new ServiceLayerException("Reset hard failed for site " + siteId, e);
} finally {
generalLockService.unlock(gitLockKey);
}
return true;
}
use of org.craftercms.studio.api.v1.constant.StudioConstants.PATTERN_SITE in project studio by craftercms.
the class RepositoryManagementServiceInternalImpl method addRemote.
@Override
public boolean addRemote(String siteId, RemoteRepository remoteRepository) throws ServiceLayerException, InvalidRemoteUrlException {
boolean isValid = false;
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, siteId);
generalLockService.lock(gitLockKey);
try {
logger.debug("Add remote " + remoteRepository.getRemoteName() + " to the sandbox repo for the site " + siteId);
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
Repository repo = helper.getRepository(siteId, SANDBOX);
try (Git git = new Git(repo)) {
Config storedConfig = repo.getConfig();
Set<String> remotes = storedConfig.getSubsections("remote");
if (remotes.contains(remoteRepository.getRemoteName())) {
throw new RemoteAlreadyExistsException(remoteRepository.getRemoteName());
}
RemoteAddCommand remoteAddCommand = git.remoteAdd();
remoteAddCommand.setName(remoteRepository.getRemoteName());
remoteAddCommand.setUri(new URIish(remoteRepository.getRemoteUrl()));
retryingRepositoryOperationFacade.call(remoteAddCommand);
try {
isValid = helper.isRemoteValid(git, remoteRepository.getRemoteName(), remoteRepository.getAuthenticationType(), remoteRepository.getRemoteUsername(), remoteRepository.getRemotePassword(), remoteRepository.getRemoteToken(), remoteRepository.getRemotePrivateKey());
} finally {
if (!isValid) {
RemoteRemoveCommand remoteRemoveCommand = git.remoteRemove();
remoteRemoveCommand.setRemoteName(remoteRepository.getRemoteName());
retryingRepositoryOperationFacade.call(remoteRemoveCommand);
List<Ref> resultRemoteBranches = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE).call();
List<String> branchesToDelete = new ArrayList<String>();
for (Ref remoteBranchRef : resultRemoteBranches) {
if (remoteBranchRef.getName().startsWith(Constants.R_REMOTES + remoteRepository.getRemoteName())) {
branchesToDelete.add(remoteBranchRef.getName());
}
}
if (CollectionUtils.isNotEmpty(branchesToDelete)) {
DeleteBranchCommand delBranch = git.branchDelete();
String[] array = new String[branchesToDelete.size()];
delBranch.setBranchNames(branchesToDelete.toArray(array));
delBranch.setForce(true);
retryingRepositoryOperationFacade.call(delBranch);
}
}
}
} catch (URISyntaxException e) {
logger.error("Remote URL is invalid " + remoteRepository.getRemoteUrl(), e);
throw new InvalidRemoteUrlException();
} catch (GitAPIException | IOException e) {
logger.error("Error while adding remote " + remoteRepository.getRemoteName() + " (url: " + remoteRepository.getRemoteUrl() + ") " + "for site " + siteId, e);
throw new ServiceLayerException("Error while adding remote " + remoteRepository.getRemoteName() + " (url: " + remoteRepository.getRemoteUrl() + ") for site " + siteId, e);
}
if (isValid) {
insertRemoteToDb(siteId, remoteRepository);
}
} catch (CryptoException e) {
throw new ServiceLayerException(e);
} finally {
generalLockService.unlock(gitLockKey);
}
return isValid;
}
use of org.craftercms.studio.api.v1.constant.StudioConstants.PATTERN_SITE in project studio by craftercms.
the class StudioClusterSandboxRepoSyncTask method createSiteFromRemote.
protected boolean createSiteFromRemote(String siteId, long localNodeId, List<ClusterSiteRecord> clusterSiteRecords) throws CryptoException, ServiceLayerException {
// Clone from the first node in the cluster (it doesn't matter which one to clone from, so pick the first)
// we will eventually to catch up to the latest
boolean cloned = false;
int idx = 0;
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, siteId);
if (generalLockService.tryLock(gitLockKey)) {
try {
Optional<ClusterSiteRecord> csr = clusterSiteRecords.stream().filter(x -> StringUtils.equals(x.getState(), STATE_CREATED) && !(x.getClusterNodeId() == localNodeId)).findFirst();
if (csr.isPresent()) {
ClusterMember remoteNode = clusterDao.getMemberById(csr.get().getClusterNodeId());
logger.debug("Cloning " + SANDBOX + " repository for site " + siteId + " from " + remoteNode.getLocalAddress());
// prepare a new folder for the cloned repository
Path siteSandboxPath = buildRepoPath(siteId);
File localPath = siteSandboxPath.toFile();
// then clone
logger.debug("Cloning from " + remoteNode.getGitUrl() + " to " + localPath);
CloneCommand cloneCommand = Git.cloneRepository();
Git cloneResult = null;
try {
if (localPath.exists()) {
FileUtils.forceDelete(localPath);
}
final Path tempKey = Files.createTempFile(UUID.randomUUID().toString(), ".tmp");
logger.debug("Add user credentials if provided");
studioClusterUtils.configureAuthenticationForCommand(remoteNode, cloneCommand, tempKey);
String cloneUrl = remoteNode.getGitUrl().replace("{siteId}", siteId);
cloneUrl = cloneUrl + "/" + studioConfiguration.getProperty(SANDBOX_PATH);
logger.debug("Executing clone command");
Git gitClone = cloneResult = cloneCommand.setURI(cloneUrl).setRemote(remoteNode.getGitRemoteName()).setDirectory(localPath).setCloneAllBranches(true).call();
Files.deleteIfExists(tempKey);
cloned = validateRepository(gitClone.getRepository());
} catch (InvalidRemoteException e) {
logger.error("Invalid remote repository: " + remoteNode.getGitRemoteName() + " (" + remoteNode.getGitUrl() + ")", e);
} catch (TransportException e) {
if (StringUtils.endsWithIgnoreCase(e.getMessage(), "not authorized")) {
logger.error("Bad credentials or read only repository: " + remoteNode.getGitRemoteName() + " (" + remoteNode.getGitUrl() + ")", e);
} else {
logger.error("Remote repository not found: " + remoteNode.getGitRemoteName() + " (" + remoteNode.getGitUrl() + ")", e);
}
} catch (GitAPIException | IOException e) {
logger.error("Error while creating repository for site with path" + siteSandboxPath, e);
} finally {
if (cloneResult != null) {
cloneResult.close();
}
}
}
} finally {
generalLockService.unlock(gitLockKey);
}
} else {
logger.debug("Failed to get lock " + gitLockKey);
}
return cloned;
}
Aggregations