[Toaster] [review-request][PATCH] bitbake: toaster: Enforce unique layer names

Michael Wood michael.g.wood at intel.com
Mon Mar 2 07:00:49 PST 2015


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]

Signed-off-by: Michael Wood <michael.g.wood at intel.com>
---
 .../toaster/toastergui/static/js/importlayer.js    | 94 +++++++++-------------
 .../toaster/toastergui/templates/importlayer.html  | 39 +++++++--
 bitbake/lib/toaster/toastergui/views.py            | 11 ++-
 3 files changed, 82 insertions(+), 62 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/static/js/importlayer.js b/bitbake/lib/toaster/toastergui/static/js/importlayer.js
index 9d54286..d14a8ab 100644
--- a/bitbake/lib/toaster/toastergui/static/js/importlayer.js
+++ b/bitbake/lib/toaster/toastergui/static/js/importlayer.js
@@ -148,7 +148,6 @@ function importLayerPageInit (ctx) {
           headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
           success: function (data) {
             if (data.error != "ok") {
-              show_error_message(data, layerData);
               console.log(data.error);
             } else {
               /* Success layer import now go to the project page */
@@ -164,59 +163,7 @@ function importLayerPageInit (ctx) {
     }
   });
 
-  function show_error_message(error, layerData) {
-
-    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) {
+  function enable_import_btn(enabled) {
     var importAndAddHint = $("#import-and-add-hint");
 
     if (enabled) {
@@ -244,6 +191,38 @@ function importLayerPageInit (ctx) {
       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() {
     check_form();
   });
@@ -260,6 +239,13 @@ function importLayerPageInit (ctx) {
       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
      * reason.
      */
diff --git a/bitbake/lib/toaster/toastergui/templates/importlayer.html b/bitbake/lib/toaster/toastergui/templates/importlayer.html
index 19d2fc4..c687c12 100644
--- a/bitbake/lib/toaster/toastergui/templates/importlayer.html
+++ b/bitbake/lib/toaster/toastergui/templates/importlayer.html
@@ -51,26 +51,51 @@
                       <div class="control-group" id="layer-name-ctrl">
                         <label class="control-label" for="import-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>
                         <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="duplicated-layer-name-hint"></span>
                         </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">
                             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>
 
                         <input type="text" id="layer-git-repo-url" class="input-xxlarge" required>
                         <label class="project-form" for="layer-subdir">
                             Repository subdirectory
                             <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>
                         <input type="text"  id="layer-subdir">
 
@@ -83,13 +108,16 @@
                                 <span class="help-inline" style="diaply:none;" id="invalid-layer-revision-hint"></span>
                             </div>
                           </div>
+                        </span>
 
                     </fieldset>
+
+                    <span class="fields-apart-from-layer-name">
                     <fieldset class="air">
                         <legend>
                             Layer dependencies
                             <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>
                         <ul class="unstyled configuration-list" id="layer-deps-list">
                         </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>
                         <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>
+                  </span>
                   </form>
 
 {% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 4f4ae67..b078d90 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -2227,9 +2227,14 @@ if toastermain.settings.MANAGED:
 
 
             def _lv_to_dict(x):
-                return {"id": x.pk, "name": x.layer.name, "tooltip": x.layer.vcs_url+" | "+x.commit,
-                        "detail": "(" + x.layer.vcs_url + (")" if x.up_branch == None else " | "+x.up_branch.name+")"),
-                        "giturl": x.layer.vcs_url, "layerdetailurl" : reverse('layerdetails', args=(x.pk,))}
+                return {"id": x.pk,
+                        "name": x.layer.name,
+                        "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
-- 
2.1.0



More information about the toaster mailing list