@@ -118,8 +118,8 @@  class EditLayerForm(StyledModelForm):
 
     def clean_name(self):
         name = self.cleaned_data['name'].strip()
-        if re.compile(r'[^a-z0-9-]').search(name):
-            raise forms.ValidationError("Name must only contain alphanumeric characters and dashes")
+        if re.compile(r'[^a-z0-9-\.]').search(name):
+            raise forms.ValidationError("Name must only contain alphanumeric characters, dashes or periods")
         if name.startswith('-'):
             raise forms.ValidationError("Name must not start with a dash")
         if name.endswith('-'):
@@ -46,7 +46,7 @@  urlpatterns = [
 
     re_path(r'^layers/$',
         RedirectView.as_view(url=reverse_lazy('layer_list', args=('master',)), permanent=False)),
-    re_path(r'^layer/(?P<slug>[-\w]+)/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/$',
         RedirectParamsView.as_view(permanent=False), {'redirect_name': 'layer_item', 'branch': 'master'}),
     re_path(r'^recipes/$',
         RedirectView.as_view(url=reverse_lazy('recipe_search', args=('master',)), permanent=False)),
@@ -65,23 +65,23 @@  urlpatterns = [
         LayerReviewListView.as_view(
             template_name='layerindex/reviewlist.html'),
         name='layer_list_review'),
-    re_path(r'^review/(?P<slug>[-\w]+)/$',
+    re_path(r'^review/(?P<slug>[-\.\w]+)/$',
         LayerReviewDetailView.as_view(
             template_name='layerindex/reviewdetail.html'),
         name='layer_review'),
-    re_path(r'^layer/(?P<slug>[-\w]+)/addnote/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/addnote/$',
         edit_layernote_view, {'template_name': 'layerindex/editlayernote.html'}, name="add_layernote"),
-    re_path(r'^layer/(?P<slug>[-\w]+)/editnote/(?P<pk>[-\w]+)/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/editnote/(?P<pk>[-\w]+)/$',
         edit_layernote_view, {'template_name': 'layerindex/editlayernote.html'}, name="edit_layernote"),
-    re_path(r'^layer/(?P<slug>[-\w]+)/deletenote/(?P<pk>[-\w]+)/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/deletenote/(?P<pk>[-\w]+)/$',
         delete_layernote_view, {'template_name': 'layerindex/deleteconfirm.html'}, name="delete_layernote"),
-    re_path(r'^layer/(?P<slug>[-\w]+)/delete/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/delete/$',
         delete_layer_view, {'template_name': 'layerindex/deleteconfirm.html'}, name="delete_layer"),
     re_path(r'^recipe/(?P<pk>[-\w]+)/$',
         RecipeDetailView.as_view(
             template_name='layerindex/recipedetail.html'),
         name='recipe'),
-    re_path(r'^layer/(?P<name>[-\w]+)/publish/$', publish_view, name="publish"),
+    re_path(r'^layer/(?P<name>[-\.\w]+)/publish/$', publish_view, name="publish"),
     re_path(r'^layerupdate/(?P<pk>[-\w]+)/$',
         LayerUpdateDetailView.as_view(
             template_name='layerindex/layerupdate.html'),
@@ -17,11 +17,11 @@  urlpatterns = [
         LayerListView.as_view(
             template_name='layerindex/layers.html'),
             name='layer_list'),
-    re_path(r'^layer/(?P<slug>[-\w]+)/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/$',
         LayerDetailView.as_view(
             template_name='layerindex/detail.html'),
             name='layer_item'),
-    re_path(r'^layer/(?P<slug>[-\w]+)/recipes/csv/$',
+    re_path(r'^layer/(?P<slug>[-\.\w]+)/recipes/csv/$',
         layer_export_recipes_csv_view,
         name='layer_export_recipes_csv'),
     re_path(r'^recipes/$',
@@ -40,8 +40,8 @@  urlpatterns = [
         ClassSearchView.as_view(
             template_name='layerindex/classes.html'),
             name='class_search'),
-    re_path(r'^edit/(?P<slug>[-\w]+)/$', edit_layer_view, {'template_name': 'layerindex/editlayer.html'}, name="edit_layer"),
-    re_path(r'^update/(?P<slug>[-\w]+)/$', update_layer_view, {'template_name': 'layerindex/updatelayer.html'}, name="update_layer"),
+    re_path(r'^edit/(?P<slug>[-\.\w]+)/$', edit_layer_view, {'template_name': 'layerindex/editlayer.html'}, name="edit_layer"),
+    re_path(r'^update/(?P<slug>[-\.\w]+)/$', update_layer_view, {'template_name': 'layerindex/updatelayer.html'}, name="update_layer"),
     re_path(r'^duplicates/$',
         DuplicatesView.as_view(
             template_name='layerindex/duplicates.html'),
 
  
There is nothing preventing a period in a layer name from the BitBake perspective. For example, https://github.com/webosose/meta-webosose has: meta-webos-backports/meta-webos-backports-4.1 [YOCTO #15373] Signed-off-by: Tim Orling <tim.orling@konsulko.com> --- layerindex/forms.py | 4 ++-- layerindex/urls.py | 14 +++++++------- layerindex/urls_branch.py | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-)