bitbake: toaster: Enforce unique layer names
We had some clever functionality to manage duplicate layer names by using layer versions and new revisions, unfortunately this was too opaque to the user. [YOCTO #7337] (Bitbake rev: 4590cfcb2d5e26518e04f8abc8e7c2dad973f6d2) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
d8ae3ac160
commit
dcbfc74c3c
|
@ -148,7 +148,6 @@ function importLayerPageInit (ctx) {
|
||||||
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
|
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (data.error != "ok") {
|
if (data.error != "ok") {
|
||||||
show_error_message(data, layerData);
|
|
||||||
console.log(data.error);
|
console.log(data.error);
|
||||||
} else {
|
} else {
|
||||||
/* Success layer import now go to the project page */
|
/* Success layer import now go to the project page */
|
||||||
|
@ -164,59 +163,7 @@ function importLayerPageInit (ctx) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function show_error_message(error, layerData) {
|
function enable_import_btn(enabled) {
|
||||||
|
|
||||||
var errorMsg = $("#import-error").fadeIn();
|
|
||||||
var errorType = error.error;
|
|
||||||
var body = errorMsg.children("p");
|
|
||||||
var title = errorMsg.children("h3");
|
|
||||||
var optionsList = errorMsg.children("ul");
|
|
||||||
var invalidLayerRevision = $("#invalid-layer-revision-hint");
|
|
||||||
var layerRevisionCtrl = $("#layer-revision-ctrl");
|
|
||||||
|
|
||||||
/* remove any existing items */
|
|
||||||
optionsList.children().each(function(){ $(this).remove(); });
|
|
||||||
body.text("");
|
|
||||||
title.text("");
|
|
||||||
invalidLayerRevision.hide();
|
|
||||||
layerNameCtrl.removeClass("error");
|
|
||||||
layerRevisionCtrl.removeClass("error");
|
|
||||||
|
|
||||||
switch (errorType){
|
|
||||||
case 'hint-layer-version-exists':
|
|
||||||
title.text("This layer already exists");
|
|
||||||
body.html("A layer <strong>"+layerData.name+"</strong> already exists with this Git repository URL and this revision. You can:");
|
|
||||||
optionsList.append("<li>Import <strong>"+layerData.name+"</strong> with a different revision </li>");
|
|
||||||
optionsList.append("<li>or <a href=\""+ctx.layerDetailsUrl+error.existing_layer_version+"/\" >change the revision of the existing layer</a></li>");
|
|
||||||
|
|
||||||
layerRevisionCtrl.addClass("error");
|
|
||||||
|
|
||||||
invalidLayerRevision.html("A layer <strong>"+layerData.name+"</strong> already exists with this revision.<br />You can import <strong>"+layerData.name+"</strong> with a different revision");
|
|
||||||
invalidLayerRevision.show();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'hint-layer-exists-with-different-url':
|
|
||||||
title.text("This layer already exists");
|
|
||||||
body.html("A layer <strong>"+layerData.name+"</strong> already exists with a different Git repository URL:<p style='margin-top:10px;'><strong>"+error.current_url+"</strong></p><p>You can:</p>");
|
|
||||||
optionsList.append("<li>Import the layer under a different name</li>");
|
|
||||||
optionsList.append("<li>or <a href=\""+ctx.layerDetailsUrl+error.current_id+"/\" >change the Git repository URL of the existing layer</a></li>");
|
|
||||||
duplicatedLayerName.html("A layer <strong>"+layerData.name+"</strong> already exists with a different Git repository URL.<br />To import this layer give it a different name.");
|
|
||||||
duplicatedLayerName.show();
|
|
||||||
layerNameCtrl.addClass("error");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'hint-layer-exists':
|
|
||||||
title.text("This layer already exists");
|
|
||||||
body.html("A layer <strong>"+layerData.name+"</strong> already exists. You can:");
|
|
||||||
optionsList.append("<li>Import the layer under a different name</li>");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
title.text("Error")
|
|
||||||
body.text(data.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable_import_btn (enabled) {
|
|
||||||
var importAndAddHint = $("#import-and-add-hint");
|
var importAndAddHint = $("#import-and-add-hint");
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
@ -244,6 +191,38 @@ function importLayerPageInit (ctx) {
|
||||||
enable_import_btn(true);
|
enable_import_btn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function layerExistsError(layer){
|
||||||
|
var dupLayerInfo = $("#duplicate-layer-info");
|
||||||
|
dupLayerInfo.find(".dup-layer-name").text(layer.name);
|
||||||
|
dupLayerInfo.find(".dup-layer-link").attr("href", layer.layerdetailurl);
|
||||||
|
dupLayerInfo.find("#dup-layer-vcs-url").text(layer.giturl);
|
||||||
|
dupLayerInfo.find("#dup-layer-revision").text(layer.revision);
|
||||||
|
|
||||||
|
$(".fields-apart-from-layer-name").fadeOut(function(){
|
||||||
|
|
||||||
|
dupLayerInfo.fadeIn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
layerNameInput.on('blur', function() {
|
||||||
|
if (!$(this).val()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var name = $(this).val();
|
||||||
|
|
||||||
|
/* Check if the layer name exists */
|
||||||
|
$.getJSON(ctx.xhrDataTypeaheadUrl, { type : "layers", project_id: ctx.projectId, include_added: "true" , value: name }, function(layer) {
|
||||||
|
if (layer.list.length > 0) {
|
||||||
|
for (var i in layer.list){
|
||||||
|
if (layer.list[i].name == name) {
|
||||||
|
console.log(layer.list[i])
|
||||||
|
layerExistsError(layer.list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
vcsURLInput.on('input', function() {
|
vcsURLInput.on('input', function() {
|
||||||
check_form();
|
check_form();
|
||||||
});
|
});
|
||||||
|
@ -260,6 +239,13 @@ function importLayerPageInit (ctx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($("#duplicate-layer-info").css("display") != "None"){
|
||||||
|
$("#duplicate-layer-info").fadeOut(function(){
|
||||||
|
$(".fields-apart-from-layer-name").show();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't remove the error class if we're displaying the error for another
|
/* Don't remove the error class if we're displaying the error for another
|
||||||
* reason.
|
* reason.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -51,26 +51,51 @@
|
||||||
<div class="control-group" id="layer-name-ctrl">
|
<div class="control-group" id="layer-name-ctrl">
|
||||||
<label class="control-label" for="import-layer-name">
|
<label class="control-label" for="import-layer-name">
|
||||||
Layer name
|
Layer name
|
||||||
<span class="icon-question-sign get-help" title="Something like 'meta-mylayer'. Your layer name must be unique and can only include letters, numbers and dashes" />
|
<span class="icon-question-sign get-help" title="Something like 'meta-mylayer'. Your layer name must be unique and can only include letters, numbers and dashes"></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input id="import-layer-name" type="text" required autofocus>
|
<input id="import-layer-name" type="text" required autofocus data-autocomplete="off" data-provide="typeahead">
|
||||||
<span class="help-inline" style="display: none;" id="invalid-layer-name-hint">A valid layer name can only include letters, numbers and dashes</span>
|
<span class="help-inline" style="display: none;" id="invalid-layer-name-hint">A valid layer name can only include letters, numbers and dashes</span>
|
||||||
<span class="help-inline" style="display: none;" id="duplicated-layer-name-hint"></span>
|
<span class="help-inline" style="display: none;" id="duplicated-layer-name-hint"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<span id="duplicate-layer-info" style="display:none">
|
||||||
|
<div class="alert warning">
|
||||||
|
<h3>A layer called <a href="" class="dup-layer-link"><span class="dup-layer-name"></span></a> already exists</h3>
|
||||||
|
<p>Layer names must be unqiue. Please use a different layer name.</p>
|
||||||
|
</div>
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
The <span class="dup-layer-name"></span> repository url is
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<span id="dup-layer-vcs-url"></span>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
The <span class="dup-layer-name"></span> revision is
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
<span id="dup-layer-revision"></span>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<p><a href="" class="dup-layer-link">View the <span class="dup-layer-name"></span> layer information</a></p>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="fields-apart-from-layer-name">
|
||||||
<label for="layer-git-repo-url" class="project-form">
|
<label for="layer-git-repo-url" class="project-form">
|
||||||
Git repository URL
|
Git repository URL
|
||||||
<span class="icon-question-sign get-help" title="Fetch/clone URL of the repository. Currently, Toaster only supports Git repositories." />
|
<span class="icon-question-sign get-help" title="Fetch/clone URL of the repository. Currently, Toaster only supports Git repositories." ></span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input type="text" id="layer-git-repo-url" class="input-xxlarge" required>
|
<input type="text" id="layer-git-repo-url" class="input-xxlarge" required>
|
||||||
<label class="project-form" for="layer-subdir">
|
<label class="project-form" for="layer-subdir">
|
||||||
Repository subdirectory
|
Repository subdirectory
|
||||||
<span class="muted">(optional)</span>
|
<span class="muted">(optional)</span>
|
||||||
<span class="icon-question-sign get-help" title="Subdirectory within the repository where the layer is located, if not in the root (usually only used if the repository contains more than one layer)" />
|
<span class="icon-question-sign get-help" title="Subdirectory within the repository where the layer is located, if not in the root (usually only used if the repository contains more than one layer)"></span>
|
||||||
</label>
|
</label>
|
||||||
<input type="text" id="layer-subdir">
|
<input type="text" id="layer-subdir">
|
||||||
|
|
||||||
|
@ -83,13 +108,16 @@
|
||||||
<span class="help-inline" style="diaply:none;" id="invalid-layer-revision-hint"></span>
|
<span class="help-inline" style="diaply:none;" id="invalid-layer-revision-hint"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</span>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<span class="fields-apart-from-layer-name">
|
||||||
<fieldset class="air">
|
<fieldset class="air">
|
||||||
<legend>
|
<legend>
|
||||||
Layer dependencies
|
Layer dependencies
|
||||||
<span class="muted">(optional)</span>
|
<span class="muted">(optional)</span>
|
||||||
<span class="icon-question-sign get-help heading-help" title="Other layers this layer depends upon" />
|
<span class="icon-question-sign get-help heading-help" title="Other layers this layer depends upon"></span>
|
||||||
</legend>
|
</legend>
|
||||||
<ul class="unstyled configuration-list" id="layer-deps-list">
|
<ul class="unstyled configuration-list" id="layer-deps-list">
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -105,6 +133,7 @@
|
||||||
<button class="btn btn-primary btn-large" data-toggle="modal" id="import-and-add-btn" data-target="#dependencies-message" disabled>Import and add to project</button>
|
<button class="btn btn-primary btn-large" data-toggle="modal" id="import-and-add-btn" data-target="#dependencies-message" disabled>Import and add to project</button>
|
||||||
<span class="help-inline" id="import-and-add-hint" style="vertical-align: middle;">To import a layer, you need to enter a repository URL, a branch, tag or commit and a layer name</span>
|
<span class="help-inline" id="import-and-add-hint" style="vertical-align: middle;">To import a layer, you need to enter a repository URL, a branch, tag or commit and a layer name</span>
|
||||||
</div>
|
</div>
|
||||||
|
</span>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2279,9 +2279,14 @@ if toastermain.settings.MANAGED:
|
||||||
|
|
||||||
|
|
||||||
def _lv_to_dict(x):
|
def _lv_to_dict(x):
|
||||||
return {"id": x.pk, "name": x.layer.name, "tooltip": x.layer.vcs_url+" | "+x.commit,
|
return {"id": x.pk,
|
||||||
"detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.up_branch.name+")"),
|
"name": x.layer.name,
|
||||||
"giturl": x.layer.vcs_url, "layerdetailurl" : reverse('layerdetails', args=(x.pk,))}
|
"tooltip": x.layer.vcs_url+" | "+x.get_vcs_reference(),
|
||||||
|
"detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.get_vcs_reference()+")"),
|
||||||
|
"giturl": x.layer.vcs_url,
|
||||||
|
"layerdetailurl" : reverse('layerdetails', args=(x.pk,)),
|
||||||
|
"revision" : x.get_vcs_reference(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# returns layers for current project release that are not in the project set, matching the name
|
# returns layers for current project release that are not in the project set, matching the name
|
||||||
|
|
Loading…
Reference in New Issue