use of org.craftercms.studio.api.v2.utils.StudioConfiguration in project studio by craftercms.
the class GitContentRepository method getContentChildren.
@Override
public RepositoryItem[] getContentChildren(String site, String path) {
// TODO: SJ: Rethink this API call for 3.1+
final List<RepositoryItem> retItems = new ArrayList<RepositoryItem>();
try {
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
Repository repo = helper.getRepository(site, StringUtils.isEmpty(site) ? GLOBAL : SANDBOX);
RevTree tree = helper.getTreeForLastCommit(repo);
try (TreeWalk tw = TreeWalk.forPath(repo, helper.getGitPath(path), tree)) {
if (tw != null) {
// Loop for all children and gather path of item excluding the item, file/folder name, and
// whether or not it's a folder
ObjectLoader loader = repo.open(tw.getObjectId(0));
if (loader.getType() == OBJ_TREE) {
int depth = tw.getDepth();
tw.enterSubtree();
while (tw.next()) {
if (tw.getDepth() == depth + 1) {
RepositoryItem item = new RepositoryItem();
item.name = tw.getNameString();
String visitFolderPath = FILE_SEPARATOR + tw.getPathString();
loader = repo.open(tw.getObjectId(0));
item.isFolder = loader.getType() == OBJ_TREE;
int lastIdx = visitFolderPath.lastIndexOf(FILE_SEPARATOR + item.name);
if (lastIdx > 0) {
item.path = visitFolderPath.substring(0, lastIdx);
}
if (!ArrayUtils.contains(IGNORE_FILES, item.name)) {
retItems.add(item);
}
}
}
tw.close();
} else {
logger.debug("Object is not tree for site: " + site + " path: " + path + " - it does not have children");
}
} else {
String gitPath = helper.getGitPath(path);
if (StringUtils.isEmpty(gitPath) || gitPath.equals(".")) {
try (TreeWalk treeWalk = new TreeWalk(repo)) {
treeWalk.addTree(tree);
while (treeWalk.next()) {
ObjectLoader loader = repo.open(treeWalk.getObjectId(0));
RepositoryItem item = new RepositoryItem();
item.name = treeWalk.getNameString();
String visitFolderPath = FILE_SEPARATOR + treeWalk.getPathString();
loader = repo.open(treeWalk.getObjectId(0));
item.isFolder = loader.getType() == OBJ_TREE;
int lastIdx = visitFolderPath.lastIndexOf(FILE_SEPARATOR + item.name);
if (lastIdx > 0) {
item.path = visitFolderPath.substring(0, lastIdx);
} else {
item.path = EMPTY;
}
if (!ArrayUtils.contains(IGNORE_FILES, item.name)) {
retItems.add(item);
}
}
} catch (IOException e) {
logger.error("Error while getting children for site: " + site + " path: " + path, e);
}
}
}
} catch (IOException e) {
logger.error("Error while getting children for site: " + site + " path: " + path, e);
}
} catch (IOException | CryptoException e) {
logger.error("Failed to create RevTree for site: " + site + " path: " + path, e);
}
RepositoryItem[] items = new RepositoryItem[retItems.size()];
items = retItems.toArray(items);
return items;
}
use of org.craftercms.studio.api.v2.utils.StudioConfiguration in project studio by craftercms.
the class GitContentRepository method addRemote.
@Override
public boolean addRemote(String siteId, String remoteName, String remoteUrl, String authenticationType, String remoteUsername, String remotePassword, String remoteToken, String remotePrivateKey) throws InvalidRemoteUrlException, ServiceLayerException {
boolean isValid = false;
try {
logger.debug("Add remote " + remoteName + " 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(remoteName)) {
throw new RemoteAlreadyExistsException(remoteName);
}
RemoteAddCommand remoteAddCommand = git.remoteAdd();
remoteAddCommand.setName(remoteName);
remoteAddCommand.setUri(new URIish(remoteUrl));
retryingRepositoryOperationFacade.call(remoteAddCommand);
try {
isValid = isRemoteValid(git, remoteName, authenticationType, remoteUsername, remotePassword, remoteToken, remotePrivateKey);
} finally {
if (!isValid) {
RemoteRemoveCommand remoteRemoveCommand = git.remoteRemove();
remoteRemoveCommand.setRemoteName(remoteName);
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 + remoteName)) {
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 | ClassCastException e) {
logger.error("Remote URL is invalid " + remoteUrl, e);
throw new InvalidRemoteUrlException("Remote URL is invalid " + remoteUrl, e);
} catch (GitAPIException | IOException e) {
logger.error("Error while adding remote " + remoteName + " (url: " + remoteUrl + ") for site " + siteId, e);
throw new ServiceLayerException("Error while adding remote " + remoteName + " (url: " + remoteUrl + ") for site " + siteId, e);
}
if (isValid) {
insertRemoteToDb(siteId, remoteName, remoteUrl, authenticationType, remoteUsername, remotePassword, remoteToken, remotePrivateKey);
}
} catch (CryptoException e) {
throw new ServiceLayerException(e);
}
return isValid;
}
use of org.craftercms.studio.api.v2.utils.StudioConfiguration in project studio by craftercms.
the class GitContentRepository method moveContent.
@Override
public Map<String, String> moveContent(String site, String fromPath, String toPath, String newName) {
Map<String, String> toRet = new TreeMap<String, String>();
String commitId;
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, site);
generalLockService.lock(gitLockKey);
try {
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
synchronized (helper.getRepository(site, StringUtils.isEmpty(site) ? GLOBAL : SANDBOX)) {
Repository repo = helper.getRepository(site, StringUtils.isEmpty(site) ? GLOBAL : SANDBOX);
String gitFromPath = helper.getGitPath(fromPath);
String gitToPath;
if (StringUtils.isEmpty(newName)) {
gitToPath = helper.getGitPath(toPath);
} else {
gitToPath = helper.getGitPath(toPath + FILE_SEPARATOR + newName);
}
try (Git git = new Git(repo)) {
// Check if destination is a file, then this is a rename operation
// Perform rename and exit
Path sourcePath = Paths.get(repo.getDirectory().getParent(), gitFromPath);
File sourceFile = sourcePath.toFile();
Path targetPath = Paths.get(repo.getDirectory().getParent(), gitToPath);
File targetFile = targetPath.toFile();
if (sourceFile.getCanonicalFile().equals(targetFile.getCanonicalFile())) {
sourceFile.renameTo(targetFile);
} else {
if (targetFile.isFile()) {
if (sourceFile.isFile()) {
sourceFile.renameTo(targetFile);
} else {
// This is not a valid operation
logger.error("Invalid move operation: Trying to rename a directory to a file " + "for site: " + site + " fromPath: " + fromPath + " toPath: " + toPath + " newName: " + newName);
}
} else if (sourceFile.isDirectory()) {
// Check if we're moving a single file or whole subtree
File[] dirList = sourceFile.listFiles();
for (File child : dirList) {
if (!child.equals(sourceFile)) {
FileUtils.moveToDirectory(child, targetFile, true);
}
}
FileUtils.deleteDirectory(sourceFile);
} else {
if (sourceFile.isFile()) {
FileUtils.moveFile(sourceFile, targetFile);
} else {
FileUtils.moveToDirectory(sourceFile, targetFile, true);
}
}
}
// The operation is done on disk, now it's time to commit
AddCommand addCommand = git.add().addFilepattern(gitToPath);
retryingRepositoryOperationFacade.call(addCommand);
StatusCommand statusCommand = git.status().addPath(gitToPath);
Status gitStatus = retryingRepositoryOperationFacade.call(statusCommand);
Set<String> changeSet = gitStatus.getAdded();
for (String pathToCommit : changeSet) {
String pathRemoved = pathToCommit.replace(gitToPath, gitFromPath);
CommitCommand commitCommand = git.commit().setOnly(pathToCommit).setOnly(pathRemoved).setAuthor(helper.getCurrentUserIdent()).setCommitter(helper.getCurrentUserIdent()).setMessage(helper.getCommitMessage(REPO_MOVE_CONTENT_COMMIT_MESSAGE).replaceAll(PATTERN_FROM_PATH, fromPath).replaceAll(PATTERN_TO_PATH, toPath + (StringUtils.isNotEmpty(newName) ? newName : EMPTY)));
RevCommit commit = retryingRepositoryOperationFacade.call(commitCommand);
commitId = commit.getName();
toRet.put(pathToCommit, commitId);
}
}
}
} catch (IOException | GitAPIException | ServiceLayerException | UserNotFoundException | CryptoException e) {
logger.error("Error while moving content for site: " + site + " fromPath: " + fromPath + " toPath: " + toPath + " newName: " + newName);
} finally {
generalLockService.unlock(gitLockKey);
}
return toRet;
}
use of org.craftercms.studio.api.v2.utils.StudioConfiguration in project studio by craftercms.
the class GitContentRepository method initialPublish.
@Override
public void initialPublish(String site, String sandboxBranch, String environment, String author, String comment) throws DeploymentException, CryptoException {
String gitLockKey = SITE_PUBLISHED_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, site);
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
Repository repo = helper.getRepository(site, PUBLISHED);
String commitId = EMPTY;
String sandboxBranchName = sandboxBranch;
if (StringUtils.isEmpty(sandboxBranchName)) {
sandboxBranchName = studioConfiguration.getProperty(REPO_SANDBOX_BRANCH);
}
generalLockService.lock(gitLockKey);
synchronized (repo) {
try (Git git = new Git(repo)) {
// fetch "origin/master"
logger.debug("Fetch from sandbox for site " + site);
git.fetch().call();
// checkout master and pull from sandbox
logger.debug("Checkout published/master branch for site " + site);
try {
CheckoutCommand checkoutCommand = git.checkout().setName(sandboxBranchName);
retryingRepositoryOperationFacade.call(checkoutCommand);
PullCommand pullCommand = git.pull().setRemote(DEFAULT_REMOTE_NAME).setRemoteBranchName(sandboxBranchName).setStrategy(THEIRS);
retryingRepositoryOperationFacade.call(pullCommand);
} catch (RefNotFoundException e) {
logger.error("Failed to checkout published master and to pull content from sandbox for site " + site, e);
throw new DeploymentException("Failed to checkout published master and to pull content from " + "sandbox for site " + site);
}
// checkout environment branch
logger.debug("Checkout environment branch " + environment + " for site " + site);
try {
CheckoutCommand checkoutCommand = git.checkout().setCreateBranch(true).setForce(true).setStartPoint(sandboxBranchName).setUpstreamMode(TRACK).setName(environment);
retryingRepositoryOperationFacade.call(checkoutCommand);
} catch (RefNotFoundException e) {
logger.info("Not able to find branch " + environment + " for site " + site + ". Creating new branch");
}
// tag
PersonIdent authorIdent = helper.getAuthorIdent(author);
ZonedDateTime publishDate = ZonedDateTime.now(UTC);
String tagName = publishDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HHmmssSSSX")) + "_published_on_" + publishDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HHmmssSSSX"));
TagCommand tagCommand = git.tag().setTagger(authorIdent).setName(tagName).setMessage(comment);
retryingRepositoryOperationFacade.call(tagCommand);
} catch (Exception e) {
logger.error("Error when publishing site " + site + " to environment " + environment, e);
throw new DeploymentException("Error when publishing site " + site + " to environment " + environment + " [commit ID = " + commitId + "]");
} finally {
generalLockService.unlock(gitLockKey);
}
}
}
use of org.craftercms.studio.api.v2.utils.StudioConfiguration in project studio by craftercms.
the class GitContentRepository method createSitePushToRemote.
@Override
public boolean createSitePushToRemote(String siteId, String remoteName, String remoteUrl, String authenticationType, String remoteUsername, String remotePassword, String remoteToken, String remotePrivateKey, boolean createAsOrphan) throws InvalidRemoteRepositoryException, InvalidRemoteRepositoryCredentialsException, RemoteRepositoryNotFoundException, RemoteRepositoryNotBareException, ServiceLayerException {
boolean toRet = true;
String gitLockKey = SITE_SANDBOX_REPOSITORY_GIT_LOCK.replaceAll(PATTERN_SITE, siteId);
generalLockService.lock(gitLockKey);
try {
GitRepositoryHelper helper = GitRepositoryHelper.getHelper(studioConfiguration, securityService, userServiceInternal, encryptor, generalLockService, retryingRepositoryOperationFacade);
try (Repository repo = helper.getRepository(siteId, SANDBOX)) {
try (Git git = new Git(repo)) {
boolean pkauth = false;
final Path tempKey = Files.createTempFile(UUID.randomUUID().toString(), ".tmp");
PushCommand pushCommand = git.push();
switch(authenticationType) {
case NONE:
logger.debug("No authentication");
break;
case BASIC:
logger.debug("Basic authentication");
pushCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(remoteUsername, remotePassword));
break;
case TOKEN:
logger.debug("Token based authentication");
pushCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(remoteToken, EMPTY));
break;
case PRIVATE_KEY:
logger.debug("Private key authentication");
tempKey.toFile().deleteOnExit();
pushCommand.setTransportConfigCallback(new TransportConfigCallback() {
@Override
public void configure(Transport transport) {
SshTransport sshTransport = (SshTransport) transport;
sshTransport.setSshSessionFactory(getSshSessionFactory(remotePrivateKey, tempKey));
}
});
pkauth = true;
break;
default:
throw new ServiceLayerException("Unsupported authentication type " + authenticationType);
}
logger.debug("Push site " + siteId + " to remote repository " + remoteName + "(" + remoteUrl + ")");
pushCommand.setPushAll().setRemote(remoteName);
Iterable<PushResult> result = retryingRepositoryOperationFacade.call(pushCommand);
if (pkauth)
Files.delete(tempKey);
logger.debug("Check push result to verify it was success");
Iterator<PushResult> resultIter = result.iterator();
if (resultIter.hasNext()) {
PushResult pushResult = resultIter.next();
Iterator<RemoteRefUpdate> remoteRefUpdateIterator = pushResult.getRemoteUpdates().iterator();
if (remoteRefUpdateIterator.hasNext()) {
RemoteRefUpdate update = remoteRefUpdateIterator.next();
if (update.getStatus().equals(REJECTED_NONFASTFORWARD)) {
logger.error("Remote repository: " + remoteName + " (" + remoteUrl + ") is not bare repository");
throw new RemoteRepositoryNotBareException("Remote repository: " + remoteName + " (" + remoteUrl + ") is not bare repository");
}
}
}
} catch (InvalidRemoteException e) {
logger.error("Invalid remote repository: " + remoteName + " (" + remoteUrl + ")", e);
throw new InvalidRemoteRepositoryException("Invalid remote repository: " + remoteName + " (" + remoteUrl + ")");
} catch (TransportException e) {
if (StringUtils.endsWithIgnoreCase(e.getMessage(), "not authorized")) {
logger.error("Bad credentials or read only repository: " + remoteName + " (" + remoteUrl + ")", e);
throw new InvalidRemoteRepositoryCredentialsException("Bad credentials or read only repository: " + remoteName + " (" + remoteUrl + ") for username " + remoteUsername, e);
} else {
logger.error("Remote repository not found: " + remoteName + " (" + remoteUrl + ")", e);
throw new RemoteRepositoryNotFoundException("Remote repository not found: " + remoteName + " (" + remoteUrl + ")");
}
} catch (ClassCastException e) {
logger.error("Wrong protocol used to access repository: " + remoteName + " (" + remoteUrl + ")", e);
throw new InvalidRemoteRepositoryCredentialsException("Wrong protocol used to access repository: " + remoteName + " (" + remoteUrl + ")", e);
} catch (ServiceLayerException | IOException e) {
logger.error("Failed to push newly created site " + siteId + " to remote repository " + remoteUrl, e);
throw new ServiceLayerException(e);
}
}
} catch (GitAPIException | CryptoException e) {
logger.error("Failed to push newly created site " + siteId + " to remote repository " + remoteUrl, e);
toRet = false;
} finally {
generalLockService.unlock(gitLockKey);
}
return toRet;
}
Aggregations