Hi,
I'm not sure if this is intended by the design of the vcs api, so i'll make my use case clear:
Currently for importing commits from a git repo, we parse the branch list to get a list of all branches. We just use VersioncontrolLabel::ensureLabel to ensure that a label is in the db. We have no idea when a branch was added, who did it or why, so we don't create any VersioncontrolOperation for branch creation, ever. This could change with a update-hook, but i'd still like to support the log parser anyways. This means we currently display a branch just as an attribute of a commit in the commit log. That's fine, but with git you'll add and remove a lot of branches, and we don't want already deleted branches to show up in the commit log. this means, when a branch is deleted in a git repo, we currently just delete the label from the database and remove it from all commits which are in a given branch (potentially many!).
The way this is done is extremly hacky, and it should at least get in the API. Maybe we should also think of a way of optimizing the deletion of branches, maybe through a boolean column deleted in the labels table, and modifying every query for versioncontrol_labels to not include labels with a status of deleted = 1. The cleanup of the table (remove deleted branches from the VCOperations and from the labels table) then could go into cron or could just get a seperate button, so it doesn't block the whole vcs_api.
The code i currently use for that is the following:
/**
* This function removes the given branch from all commits.
* @param VersioncontrolRepository $repository
* @param string $branch
* @return none
*/
function _versioncontrol_git_log_remove_branch_from_commits($repository, $branch) {
$constraints = array(
'vcs' => array('git'),
'repo_ids' => array($repository->repo_id),
'types' => array(VERSIONCONTROL_OPERATION_COMMIT),
'branches' => array($branch),
);
$commits_as_op = VersioncontrolOperationCache::getInstance()->getOperations($constraints);
foreach($commits_as_op as $commit_op) {
$new_labels = array();
foreach($commit_op->labels as $label) {
if($label->type == VERSIONCONTROL_LABEL_BRANCH && $label->name != $branch) {
$new_labels[] = $label;
}
}
$commit_op->updateLabels($new_labels);
}
}
// Deleted branches are removed, commits in them are not!
// TODO: the db_query in here is not nice, that should be part of vcapi!
foreach($branches_deleted as $branch_name) {
_versioncontrol_git_log_remove_branch_from_commits($repository, $branch_name);
db_query('DELETE FROM {versioncontrol_labels}
WHERE repo_id = %d AND type = %d AND label_id = %d',
$repository->repo_id, VERSIONCONTROL_LABEL_BRANCH,
$branch_label_list[$branch_name]->label_id);
}
Comments
Comment #1
marvil07 commentedThis still needs work, but some start is committed to the cvs repo with the entities commit, so now, to remove a branch you can you can VersioncontrolBranch->delete()
The general intention is about be able to provide a delete method on each entity.
Talking about this with sdboyer, he is planning to add an activity table that store all the things that happen, so in the entities table we can remove data to be consistent with the repository.
Comment #2
marvil07 commentedtagging
Comment #3
webchickMarking as critical, to indicate this is a migration blocker.
Comment #4
chrisstrahl commentedtagging for sprint 2
Comment #5
chrisstrahl commentedComment #6
sdboyer commentedNearly got this one done locally, gonna try to muscle it out this weekend.
Comment #7
neclimdultitle nit-pick
Comment #8
sdboyer commentedI'm gonna collapse this with #879858: Unify entity C(R)UD in favor of making it just a big unified C(R)UD issue.
Comment #9
sdboyer commented