Checkpoint a bit of work on the assemblies command
4 files changed, 35 insertions(+), 13 deletions(-)

M assemblage.gemspec
M lib/assemblage/connection.rb
M lib/assemblage/protocol.rb
M lib/assemblage/server.rb
M assemblage.gemspec +13 -10
@@ 1,26 1,26 @@ 
 # -*- encoding: utf-8 -*-
-# stub: assemblage 0.1.pre20190508145718 ruby lib
+# stub: assemblage 0.1.0.pre20190722141336 ruby lib
 
 Gem::Specification.new do |s|
   s.name = "assemblage".freeze
-  s.version = "0.1.pre20190508145718"
+  s.version = "0.1.0.pre20190722141336"
 
   s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
   s.require_paths = ["lib".freeze]
   s.authors = ["Michael Granger".freeze]
   s.cert_chain = ["certs/ged.pem".freeze]
-  s.date = "2019-05-08"
-  s.description = "Assemblage is a continuous integration library. It's intended to provide you\nwith a minimal toolkit for distributing and performing automated tasks\nfor one or more version control repositories. It makes as few assumptions as\npossible as to what those tasks might be.\n\nA task in Assemblage is called an Assembly. Assemblage has three primary parts for manipulating Assemblies: the **Assembly Server**, **Assembly\nWorkers**, and **Repositories**.\n\n<dl>\n  <dt>Assembly Server</dt>\n  <dd>Aggregates and distributes events from <em>repositories</em> to\n  <em>workers</em> via one or more \"assemblies\".</dd>\n\n  <dt>Assembly Workers</dt>\n  <dd>Listens for <em>commits</em> published by the <em>assembly server</em>,\n  checks out a <em>repository</em>, and runs an assembly script in that\n  repository.</dd>\n\n  <dt>Repository</dt>\n  <dd>A distributed version control repository. Assemblage currently supports\n  Mercurial and Git.</dd>\n\n  <dt>Commit</dt>\n  <dd>A single commit in a repository.</dd>\n\n  <dt>Assembly</dt>\n  <dd>A script that builds something, checked into the repository source in the `.assembly` directory (by default).</dd>\n</dl>".freeze
+  s.date = "2019-07-22"
+  s.description = "`assemblage`, **noun**:\n\n1. a collection of parts, as of machinery, put together to form a whole.\n2. the process of joining persons or things to form a whole.\n\nAssemblage is a continuous integration library. It's intended to provide you\nwith a minimal toolkit for distributing and performing automated tasks when\n**commits** arrive at one or more version control **repositories**. It makes as\nfew assumptions as possible as to what those tasks might be.\n\nThe product or output from such a task in Assemblage is called an Assembly.\nAssemblage has three primary parts for manipulating Assemblies: the **Assembly\nServer**, **Assembly Workers**, and **Publishers**. **Assembly Workers** listen for events set to an **Assembly Server** by a **Publisher**, and run one or more **Assembly Scripts** to assemble their products.\n\n<dl>\n  <dt>Assembly Server</dt>\n  <dd>Aggregates and distributes events from <em>repositories</em> to\n  <em>workers</em> to make one or more \"assemblies\".</dd>\n\n  <dt>Assembly Workers</dt>\n  <dd>Listens for <em>events</em> published by the <em>assembly server</em>,\n  checks out a <em>repository</em>, and runs one or more assembly scripts in\n  that repository.</dd>\n\n  <dt>Publisher</dt>\n  <dd>A client that sends events to the server from distributed version control\n  repositories. Assemblage currently supports Mercurial and Git.</dd>\n\n  <dt>Event</dt>\n  <dd>Notification of some change in a repository, e.g., a\n    <code>commit</code>.</dd>\n\n  <dt>Assembly</dt>\n  <dd>A product or collection of products built as a reaction to one or more\n    <em>events</em>.</dd>\n\n  <dt>Assembly Script</dt>\n  <dd>A script that is executed when an <em>event</em> occurs in a repository,\n  checked into the repository source in the `.assembly` directory (by\n  default).</dd>\n</dl>".freeze
   s.email = ["ged@FaerieMUD.org".freeze]
   s.executables = ["assemblage".freeze]
-  s.extra_rdoc_files = ["History.md".freeze, "LICENSE.txt".freeze, "Manifest.txt".freeze, "README.md".freeze, "History.md".freeze, "Protocol.md".freeze, "README.md".freeze]
-  s.files = [".document".freeze, ".editorconfig".freeze, ".rdoc_options".freeze, ".simplecov".freeze, "ChangeLog".freeze, "History.md".freeze, "LICENSE.txt".freeze, "Manifest.txt".freeze, "Protocol.md".freeze, "README.md".freeze, "Rakefile".freeze, "bin/assemblage".freeze, "data/assemblage/migrations/20180314_initial.rb".freeze, "lib/assemblage.rb".freeze, "lib/assemblage/auth.rb".freeze, "lib/assemblage/cli.rb".freeze, "lib/assemblage/client.rb".freeze, "lib/assemblage/command/add.rb".freeze, "lib/assemblage/command/create.rb".freeze, "lib/assemblage/command/start.rb".freeze, "lib/assemblage/db_object.rb".freeze, "lib/assemblage/mixins.rb".freeze, "lib/assemblage/protocol.rb".freeze, "lib/assemblage/server.rb".freeze, "lib/assemblage/worker.rb".freeze, "spec/.status".freeze, "spec/assemblage/auth_spec.rb".freeze, "spec/assemblage/mixins_spec.rb".freeze, "spec/assemblage/server_spec.rb".freeze, "spec/assemblage/worker_spec.rb".freeze, "spec/assemblage_spec.rb".freeze, "spec/spec_helper.rb".freeze]
+  s.extra_rdoc_files = ["Cookbook.md".freeze, "History.md".freeze, "LICENSE.txt".freeze, "Manifest.txt".freeze, "Protocol.md".freeze, "README.md".freeze, "To-Do.md".freeze, "Cookbook.md".freeze, "History.md".freeze, "Protocol.md".freeze, "README.md".freeze, "To-Do.md".freeze]
+  s.files = [".assembly/commit/on_commit-00_quality_check".freeze, ".assembly/commit/on_commit-01_test".freeze, ".assembly/tag/on_tag-00_check_signature".freeze, ".assembly/tag/on_tag-01_test".freeze, ".assembly/tag/on_tag-02_release".freeze, ".assembly/tag/on_tag-03_publish_docs".freeze, ".document".freeze, ".rdoc_options".freeze, ".simplecov".freeze, "ChangeLog".freeze, "Cookbook.md".freeze, "History.md".freeze, "LICENSE.txt".freeze, "Manifest.txt".freeze, "Protocol.md".freeze, "README.md".freeze, "Rakefile".freeze, "To-Do.md".freeze, "bin/assemblage".freeze, "data/assemblage/hooks/mercurial-hook.rb".freeze, "data/assemblage/migrations/20180314_initial.rb".freeze, "lib/assemblage.rb".freeze, "lib/assemblage/assembly_builder.rb".freeze, "lib/assemblage/assembly_result.rb".freeze, "lib/assemblage/auth.rb".freeze, "lib/assemblage/cli.rb".freeze, "lib/assemblage/client.rb".freeze, "lib/assemblage/command/client.rb".freeze, "lib/assemblage/command/publisher.rb".freeze, "lib/assemblage/command/repo.rb".freeze, "lib/assemblage/command/server.rb".freeze, "lib/assemblage/command/worker.rb".freeze, "lib/assemblage/commit.rb".freeze, "lib/assemblage/connection.rb".freeze, "lib/assemblage/db_object.rb".freeze, "lib/assemblage/event.rb".freeze, "lib/assemblage/mixins.rb".freeze, "lib/assemblage/protocol.rb".freeze, "lib/assemblage/publisher.rb".freeze, "lib/assemblage/refinements.rb".freeze, "lib/assemblage/repository.rb".freeze, "lib/assemblage/server.rb".freeze, "lib/assemblage/user.rb".freeze, "lib/assemblage/vcs_strategy.rb".freeze, "lib/assemblage/vcs_strategy/mercurial.rb".freeze, "lib/assemblage/worker.rb".freeze, "lib/cztop/monkeypatches.rb".freeze, "local.db".freeze, "spec/.status".freeze, "spec/assemblage/auth_spec.rb".freeze, "spec/assemblage/client_spec.rb".freeze, "spec/assemblage/mixins_spec.rb".freeze, "spec/assemblage/server_spec.rb".freeze, "spec/assemblage/vcs_strategy_spec.rb".freeze, "spec/assemblage/worker_spec.rb".freeze, "spec/assemblage_spec.rb".freeze, "spec/spec_helper.rb".freeze]
   s.homepage = "https://assembla.ge/".freeze
   s.licenses = ["BSD-3-Clause".freeze]
   s.rdoc_options = ["--main".freeze, "README.md".freeze]
   s.required_ruby_version = Gem::Requirement.new(">= 2.3.4".freeze)
   s.rubygems_version = "3.0.3".freeze
-  s.summary = "Assemblage is a continuous integration library".freeze
+  s.summary = "`assemblage`, **noun**:  1".freeze
 
   if s.respond_to? :specification_version then
     s.specification_version = 4

          
@@ 28,7 28,7 @@ Gem::Specification.new do |s|
     if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
       s.add_runtime_dependency(%q<loggability>.freeze, ["~> 0.11"])
       s.add_runtime_dependency(%q<configurability>.freeze, ["~> 3.2"])
-      s.add_runtime_dependency(%q<hglib>.freeze, ["~> 0.1"])
+      s.add_runtime_dependency(%q<hglib>.freeze, ["~> 0.2"])
       s.add_runtime_dependency(%q<git>.freeze, ["~> 1.3"])
       s.add_runtime_dependency(%q<gli>.freeze, ["~> 2.18"])
       s.add_runtime_dependency(%q<tty-prompt>.freeze, ["~> 0.18"])

          
@@ 36,6 36,7 @@ Gem::Specification.new do |s|
       s.add_runtime_dependency(%q<sequel>.freeze, ["~> 5.6"])
       s.add_runtime_dependency(%q<msgpack>.freeze, ["~> 1.2"])
       s.add_runtime_dependency(%q<rb-readline>.freeze, ["~> 0.5"])
+      s.add_runtime_dependency(%q<rbnacl>.freeze, ["~> 5.0"])
       s.add_runtime_dependency(%q<state_machines>.freeze, ["~> 0.5"])
       s.add_runtime_dependency(%q<cztop-reactor>.freeze, ["~> 0.7"])
       s.add_runtime_dependency(%q<pluggability>.freeze, ["~> 0.6"])

          
@@ 51,7 52,7 @@ Gem::Specification.new do |s|
     else
       s.add_dependency(%q<loggability>.freeze, ["~> 0.11"])
       s.add_dependency(%q<configurability>.freeze, ["~> 3.2"])
-      s.add_dependency(%q<hglib>.freeze, ["~> 0.1"])
+      s.add_dependency(%q<hglib>.freeze, ["~> 0.2"])
       s.add_dependency(%q<git>.freeze, ["~> 1.3"])
       s.add_dependency(%q<gli>.freeze, ["~> 2.18"])
       s.add_dependency(%q<tty-prompt>.freeze, ["~> 0.18"])

          
@@ 59,6 60,7 @@ Gem::Specification.new do |s|
       s.add_dependency(%q<sequel>.freeze, ["~> 5.6"])
       s.add_dependency(%q<msgpack>.freeze, ["~> 1.2"])
       s.add_dependency(%q<rb-readline>.freeze, ["~> 0.5"])
+      s.add_dependency(%q<rbnacl>.freeze, ["~> 5.0"])
       s.add_dependency(%q<state_machines>.freeze, ["~> 0.5"])
       s.add_dependency(%q<cztop-reactor>.freeze, ["~> 0.7"])
       s.add_dependency(%q<pluggability>.freeze, ["~> 0.6"])

          
@@ 75,7 77,7 @@ Gem::Specification.new do |s|
   else
     s.add_dependency(%q<loggability>.freeze, ["~> 0.11"])
     s.add_dependency(%q<configurability>.freeze, ["~> 3.2"])
-    s.add_dependency(%q<hglib>.freeze, ["~> 0.1"])
+    s.add_dependency(%q<hglib>.freeze, ["~> 0.2"])
     s.add_dependency(%q<git>.freeze, ["~> 1.3"])
     s.add_dependency(%q<gli>.freeze, ["~> 2.18"])
     s.add_dependency(%q<tty-prompt>.freeze, ["~> 0.18"])

          
@@ 83,6 85,7 @@ Gem::Specification.new do |s|
     s.add_dependency(%q<sequel>.freeze, ["~> 5.6"])
     s.add_dependency(%q<msgpack>.freeze, ["~> 1.2"])
     s.add_dependency(%q<rb-readline>.freeze, ["~> 0.5"])
+    s.add_dependency(%q<rbnacl>.freeze, ["~> 5.0"])
     s.add_dependency(%q<state_machines>.freeze, ["~> 0.5"])
     s.add_dependency(%q<cztop-reactor>.freeze, ["~> 0.7"])
     s.add_dependency(%q<pluggability>.freeze, ["~> 0.6"])

          
M lib/assemblage/connection.rb +16 -0
@@ 14,6 14,22 @@ class Assemblage::Connection < Assemblag
 	plugin :timestamps
 
 
+	dataset_module do
+
+		### Limit the dataset to connections which have been soft-deleted.
+		def deleted
+			return self.exclude( removed_at: nil )
+		end
+
+
+		### Limit the dataset to connections which haven't been soft-deleted.
+		def undeleted
+			return self.where( removed_at: nil )
+		end
+
+	end
+
+
 	##
 	# The routing ID associated with the socket using this connection.
 	attr_accessor :routing_id

          
M lib/assemblage/protocol.rb +1 -1
@@ 59,7 59,7 @@ module Assemblage::Protocol
 	###############
 
 	### Encode a message of the specified +type+ and return it as a CZTop::Message.
-	def encode( command, data, **header )
+	def encode( command, data=nil, **header )
 		self.log.debug "Encode %p message with data: %p, header: %p" % [ command, data, header ]
 		header = DEFAULT_HEADER.merge( symbolify_keys(header) )
 		Assemblage::Protocol.check_message_header( header )

          
M lib/assemblage/server.rb +5 -2
@@ 138,6 138,7 @@ class Assemblage::Server
 		conn = Assemblage::Connection.find_or_create( type: type.to_s, name: name ) do
 			self.log.debug "  creating connection..."
 		end
+		conn.update( removed_at: nil )
 		self.log.debug "  connection approved at %s" % [ conn.created_at ]
 
 		return conn

          
@@ 156,7 157,8 @@ class Assemblage::Server
 	### Returns +true+ if connections from the client with the specified +name+
 	### have been approved.
 	def self::connections_approved?( name )
-		return self.connection_type( name ) ? true : false
+		type = self.connection_type( name ) or return false
+		return !Assemblage::Connection.undeleted.where( name: name, type: type ).empty?
 	end
 
 

          
@@ 341,7 343,8 @@ class Assemblage::Server
 	### Handle a connection asking for any assemblies pending for it.
 	def handle_fetch_assemblies_command( connection, criteria )
 		self.log.debug "Connection %s fetched assemblies: %p" % [ connection, criteria ]
-		msg = connection.response( :)
+		msg = connection.response( :assemblies, [] )
+		self.queue_output_message( msg )
 	end