/** * Mirrors a repository and, optionally, the server's users, and/or configuration settings from a * origin Gitblit instance. * * @param registration * @throws Exception */ private void pull(FederationModel registration) throws Exception { Map<String, RepositoryModel> repositories = FederationUtils.getRepositories(registration, true); String registrationFolder = registration.folder.toLowerCase().trim(); // confirm valid characters in server alias Character c = StringUtils.findInvalidCharacter(registrationFolder); if (c != null) { logger.error( MessageFormat.format( "Illegal character ''{0}'' in folder name ''{1}'' of federation registration {2}!", c, registrationFolder, registration.name)); return; } File repositoriesFolder = new File(GitBlit.getString(Keys.git.repositoriesFolder, "git")); File registrationFolderFile = new File(repositoriesFolder, registrationFolder); registrationFolderFile.mkdirs(); // Clone/Pull the repository for (Map.Entry<String, RepositoryModel> entry : repositories.entrySet()) { String cloneUrl = entry.getKey(); RepositoryModel repository = entry.getValue(); if (!repository.hasCommits) { logger.warn( MessageFormat.format( "Skipping federated repository {0} from {1} @ {2}. Repository is EMPTY.", repository.name, registration.name, registration.url)); registration.updateStatus(repository, FederationPullStatus.SKIPPED); continue; } // Determine local repository name String repositoryName; if (StringUtils.isEmpty(registrationFolder)) { repositoryName = repository.name; } else { repositoryName = registrationFolder + "/" + repository.name; } if (registration.bare) { // bare repository, ensure .git suffix if (!repositoryName.toLowerCase().endsWith(DOT_GIT_EXT)) { repositoryName += DOT_GIT_EXT; } } else { // normal repository, strip .git suffix if (repositoryName.toLowerCase().endsWith(DOT_GIT_EXT)) { repositoryName = repositoryName.substring(0, repositoryName.indexOf(DOT_GIT_EXT)); } } // confirm that the origin of any pre-existing repository matches // the clone url String fetchHead = null; Repository existingRepository = GitBlit.self().getRepository(repositoryName); if (existingRepository == null && GitBlit.self().isCollectingGarbage(repositoryName)) { logger.warn( MessageFormat.format( "Skipping local repository {0}, busy collecting garbage", repositoryName)); continue; } if (existingRepository != null) { StoredConfig config = existingRepository.getConfig(); config.load(); String origin = config.getString("remote", "origin", "url"); RevCommit commit = JGitUtils.getCommit(existingRepository, org.eclipse.jgit.lib.Constants.FETCH_HEAD); if (commit != null) { fetchHead = commit.getName(); } existingRepository.close(); if (!origin.startsWith(registration.url)) { logger.warn( MessageFormat.format( "Skipping federated repository {0} from {1} @ {2}. Origin does not match, consider EXCLUDING.", repository.name, registration.name, registration.url)); registration.updateStatus(repository, FederationPullStatus.SKIPPED); continue; } } // clone/pull this repository CredentialsProvider credentials = new UsernamePasswordCredentialsProvider(Constants.FEDERATION_USER, registration.token); logger.info( MessageFormat.format( "Pulling federated repository {0} from {1} @ {2}", repository.name, registration.name, registration.url)); CloneResult result = JGitUtils.cloneRepository( registrationFolderFile, repository.name, cloneUrl, registration.bare, credentials); Repository r = GitBlit.self().getRepository(repositoryName); RepositoryModel rm = GitBlit.self().getRepositoryModel(repositoryName); repository.isFrozen = registration.mirror; if (result.createdRepository) { // default local settings repository.federationStrategy = FederationStrategy.EXCLUDE; repository.isFrozen = registration.mirror; repository.showRemoteBranches = !registration.mirror; logger.info(MessageFormat.format(" cloning {0}", repository.name)); registration.updateStatus(repository, FederationPullStatus.MIRRORED); } else { // fetch and update boolean fetched = false; RevCommit commit = JGitUtils.getCommit(r, org.eclipse.jgit.lib.Constants.FETCH_HEAD); String newFetchHead = commit.getName(); fetched = fetchHead == null || !fetchHead.equals(newFetchHead); if (registration.mirror) { // mirror if (fetched) { // update local branches to match the remote tracking branches for (RefModel ref : JGitUtils.getRemoteBranches(r, false, -1)) { if (ref.displayName.startsWith("origin/")) { String branch = org.eclipse.jgit.lib.Constants.R_HEADS + ref.displayName.substring(ref.displayName.indexOf('/') + 1); String hash = ref.getReferencedObjectId().getName(); JGitUtils.setBranchRef(r, branch, hash); logger.info( MessageFormat.format( " resetting {0} of {1} to {2}", branch, repository.name, hash)); } } String newHead; if (StringUtils.isEmpty(repository.HEAD)) { newHead = newFetchHead; } else { newHead = repository.HEAD; } JGitUtils.setHEADtoRef(r, newHead); logger.info( MessageFormat.format( " resetting HEAD of {0} to {1}", repository.name, newHead)); registration.updateStatus(repository, FederationPullStatus.MIRRORED); } else { // indicate no commits pulled registration.updateStatus(repository, FederationPullStatus.NOCHANGE); } } else { // non-mirror if (fetched) { // indicate commits pulled to origin/master registration.updateStatus(repository, FederationPullStatus.PULLED); } else { // indicate no commits pulled registration.updateStatus(repository, FederationPullStatus.NOCHANGE); } } // preserve local settings repository.isFrozen = rm.isFrozen; repository.federationStrategy = rm.federationStrategy; // merge federation sets Set<String> federationSets = new HashSet<String>(); if (rm.federationSets != null) { federationSets.addAll(rm.federationSets); } if (repository.federationSets != null) { federationSets.addAll(repository.federationSets); } repository.federationSets = new ArrayList<String>(federationSets); // merge indexed branches Set<String> indexedBranches = new HashSet<String>(); if (rm.indexedBranches != null) { indexedBranches.addAll(rm.indexedBranches); } if (repository.indexedBranches != null) { indexedBranches.addAll(repository.indexedBranches); } repository.indexedBranches = new ArrayList<String>(indexedBranches); } // only repositories that are actually _cloned_ from the origin // Gitblit repository are marked as federated. If the origin // is from somewhere else, these repositories are not considered // "federated" repositories. repository.isFederated = cloneUrl.startsWith(registration.url); GitBlit.self().updateConfiguration(r, repository); r.close(); } IUserService userService = null; try { // Pull USERS // TeamModels are automatically pulled because they are contained // within the UserModel. The UserService creates unknown teams // and updates existing teams. Collection<UserModel> users = FederationUtils.getUsers(registration); if (users != null && users.size() > 0) { File realmFile = new File(registrationFolderFile, registration.name + "_users.conf"); realmFile.delete(); userService = new ConfigUserService(realmFile); for (UserModel user : users) { userService.updateUserModel(user.username, user); // merge the origin permissions and origin accounts into // the user accounts of this Gitblit instance if (registration.mergeAccounts) { // reparent all repository permissions if the local // repositories are stored within subfolders if (!StringUtils.isEmpty(registrationFolder)) { if (user.permissions != null) { // pulling from >= 1.2 version Map<String, AccessPermission> copy = new HashMap<String, AccessPermission>(user.permissions); user.permissions.clear(); for (Map.Entry<String, AccessPermission> entry : copy.entrySet()) { user.setRepositoryPermission( registrationFolder + "/" + entry.getKey(), entry.getValue()); } } else { // pulling from <= 1.1 version List<String> permissions = new ArrayList<String>(user.repositories); user.repositories.clear(); for (String permission : permissions) { user.addRepositoryPermission(registrationFolder + "/" + permission); } } } // insert new user or update local user UserModel localUser = GitBlit.self().getUserModel(user.username); if (localUser == null) { // create new local user GitBlit.self().updateUserModel(user.username, user, true); } else { // update repository permissions of local user if (user.permissions != null) { // pulling from >= 1.2 version Map<String, AccessPermission> copy = new HashMap<String, AccessPermission>(user.permissions); for (Map.Entry<String, AccessPermission> entry : copy.entrySet()) { localUser.setRepositoryPermission(entry.getKey(), entry.getValue()); } } else { // pulling from <= 1.1 version for (String repository : user.repositories) { localUser.addRepositoryPermission(repository); } } localUser.password = user.password; localUser.canAdmin = user.canAdmin; GitBlit.self().updateUserModel(localUser.username, localUser, false); } for (String teamname : GitBlit.self().getAllTeamnames()) { TeamModel team = GitBlit.self().getTeamModel(teamname); if (user.isTeamMember(teamname) && !team.hasUser(user.username)) { // new team member team.addUser(user.username); GitBlit.self().updateTeamModel(teamname, team, false); } else if (!user.isTeamMember(teamname) && team.hasUser(user.username)) { // remove team member team.removeUser(user.username); GitBlit.self().updateTeamModel(teamname, team, false); } // update team repositories TeamModel remoteTeam = user.getTeam(teamname); if (remoteTeam != null) { if (remoteTeam.permissions != null) { // pulling from >= 1.2 for (Map.Entry<String, AccessPermission> entry : remoteTeam.permissions.entrySet()) { team.setRepositoryPermission(entry.getKey(), entry.getValue()); } GitBlit.self().updateTeamModel(teamname, team, false); } else if (!ArrayUtils.isEmpty(remoteTeam.repositories)) { // pulling from <= 1.1 team.addRepositoryPermissions(remoteTeam.repositories); GitBlit.self().updateTeamModel(teamname, team, false); } } } } } } } catch (ForbiddenException e) { // ignore forbidden exceptions } catch (IOException e) { logger.warn( MessageFormat.format( "Failed to retrieve USERS from federated gitblit ({0} @ {1})", registration.name, registration.url), e); } try { // Pull TEAMS // We explicitly pull these even though they are embedded in // UserModels because it is possible to use teams to specify // mailing lists or push scripts without specifying users. if (userService != null) { Collection<TeamModel> teams = FederationUtils.getTeams(registration); if (teams != null && teams.size() > 0) { for (TeamModel team : teams) { userService.updateTeamModel(team); } } } } catch (ForbiddenException e) { // ignore forbidden exceptions } catch (IOException e) { logger.warn( MessageFormat.format( "Failed to retrieve TEAMS from federated gitblit ({0} @ {1})", registration.name, registration.url), e); } try { // Pull SETTINGS Map<String, String> settings = FederationUtils.getSettings(registration); if (settings != null && settings.size() > 0) { Properties properties = new Properties(); properties.putAll(settings); FileOutputStream os = new FileOutputStream( new File( registrationFolderFile, registration.name + "_" + Constants.PROPERTIES_FILE)); properties.store(os, null); os.close(); } } catch (ForbiddenException e) { // ignore forbidden exceptions } catch (IOException e) { logger.warn( MessageFormat.format( "Failed to retrieve SETTINGS from federated gitblit ({0} @ {1})", registration.name, registration.url), e); } try { // Pull SCRIPTS Map<String, String> scripts = FederationUtils.getScripts(registration); if (scripts != null && scripts.size() > 0) { for (Map.Entry<String, String> script : scripts.entrySet()) { String scriptName = script.getKey(); if (scriptName.endsWith(".groovy")) { scriptName = scriptName.substring(0, scriptName.indexOf(".groovy")); } File file = new File(registrationFolderFile, registration.name + "_" + scriptName + ".groovy"); FileUtils.writeContent(file, script.getValue()); } } } catch (ForbiddenException e) { // ignore forbidden exceptions } catch (IOException e) { logger.warn( MessageFormat.format( "Failed to retrieve SCRIPTS from federated gitblit ({0} @ {1})", registration.name, registration.url), e); } }
private boolean validateFields() { String rname = nameField.getText(); if (StringUtils.isEmpty(rname)) { error("Please enter a repository name!"); return false; } // automatically convert backslashes to forward slashes rname = rname.replace('\\', '/'); // Automatically replace // with / rname = rname.replace("//", "/"); // prohibit folder paths if (rname.startsWith("/")) { error("Leading root folder references (/) are prohibited."); return false; } if (rname.startsWith("../")) { error("Relative folder references (../) are prohibited."); return false; } if (rname.contains("/../")) { error("Relative folder references (../) are prohibited."); return false; } // confirm valid characters in repository name Character c = StringUtils.findInvalidCharacter(rname); if (c != null) { error(MessageFormat.format("Illegal character ''{0}'' in repository name!", c)); return false; } // verify repository name uniqueness on create if (isCreate) { // force repo names to lowercase // this means that repository name checking for rpc creation // is case-insensitive, regardless of the Gitblit server's // filesystem if (repositoryNames.contains(rname.toLowerCase())) { error( MessageFormat.format( "Can not create repository ''{0}'' because it already exists.", rname)); return false; } } else { // check rename collision if (!repositoryName.equalsIgnoreCase(rname)) { if (repositoryNames.contains(rname.toLowerCase())) { error( MessageFormat.format( "Failed to rename ''{0}'' because ''{1}'' already exists.", repositoryName, rname)); return false; } } } if (accessRestriction.getSelectedItem() == null) { error("Please select access restriction!"); return false; } if (federationStrategy.getSelectedItem() == null) { error("Please select federation strategy!"); return false; } repository.name = rname; repository.description = descriptionField.getText(); repository.owner = ownerField.getSelectedItem() == null ? null : ownerField.getSelectedItem().toString(); repository.HEAD = headRefField.getSelectedItem() == null ? null : headRefField.getSelectedItem().toString(); repository.useTickets = useTickets.isSelected(); repository.useDocs = useDocs.isSelected(); repository.showRemoteBranches = showRemoteBranches.isSelected(); repository.showReadme = showReadme.isSelected(); repository.skipSizeCalculation = skipSizeCalculation.isSelected(); repository.skipSummaryMetrics = skipSummaryMetrics.isSelected(); repository.isFrozen = isFrozen.isSelected(); String ml = mailingListsField.getText(); if (!StringUtils.isEmpty(ml)) { Set<String> list = new HashSet<String>(); for (String address : ml.split("(,|\\s)")) { if (StringUtils.isEmpty(address)) { continue; } list.add(address.toLowerCase()); } repository.mailingLists = new ArrayList<String>(list); } repository.accessRestriction = (AccessRestrictionType) accessRestriction.getSelectedItem(); repository.federationStrategy = (FederationStrategy) federationStrategy.getSelectedItem(); if (repository.federationStrategy.exceeds(FederationStrategy.EXCLUDE)) { repository.federationSets = setsPalette.getSelections(); } repository.indexedBranches = indexedBranchesPalette.getSelections(); repository.preReceiveScripts = preReceivePalette.getSelections(); repository.postReceiveScripts = postReceivePalette.getSelections(); // Custom Fields repository.customFields = new LinkedHashMap<String, String>(); if (customTextfields != null) { for (JTextField field : customTextfields) { String key = field.getName(); String value = field.getText(); repository.customFields.put(key, value); } } return true; }