tangle 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ee56b345a6f81de14bbc7bb9d16fbb10f9e2174b2588140a6881bd1ff31d0d5
4
- data.tar.gz: 2172244bbb6ab3a91dff9fb4e6491fadc1f56762d984edf75c7f325b1ce9bed5
3
+ metadata.gz: 49ee5268eb1851a1087ba45efac9f00794a248dfce75aadab846f6617d91620e
4
+ data.tar.gz: cc4d0d76f99b86c5494758311637bcb4610555afb58118e059833f62992ef492
5
5
  SHA512:
6
- metadata.gz: 7bb4eeacbdf97538cef1a19738ac0260e47b56a19a6854d2de4dd735203001f7000f09239fbd3d6dcce377d8acf24a3b9647f1ddbbb2c152129b16e78de5fb16
7
- data.tar.gz: 71837d3d43769c939200f450fb823ce6e82aec754527989e93ffac3db58eac2a8a99c816c9afc648dbbf97bf101b63e78656af86e487f6d3568f40333e2fa078
6
+ metadata.gz: c785bb5d7b83a53db61c03ffff2b6a26c17659eb9f79868e4882c884d0e97339b8748d32778bd2e73bb5293b5dd3a9a9adfef22ff38ab9e0f2c1c660dc0dd09c
7
+ data.tar.gz: f042503d2a4d65f6f9ed4cce56e6ba94623ef6e57e73b306a690edce5d2276aa01a7e211d83a2d2aec096a85def0923e4c8da350eb417a37101217764c84c18e
@@ -62,14 +62,10 @@ module Tangle
62
62
  #
63
63
  # Unless a selector is provided, the subgraph contains the entire graph.
64
64
  #
65
- def subgraph(included = nil)
66
- included ||= vertices
65
+ def subgraph(included = nil, &selector)
67
66
  result = clone
68
- vertices.each do |vertex|
69
- result.remove_vertex(vertex) unless included.include?(vertex)
70
- next unless block_given?
71
- result.remove_vertex(vertex) unless yield(vertex)
72
- end
67
+ result.select_vertices!(included) unless included.nil?
68
+ result.select_vertices!(&selector) if block_given?
73
69
  result
74
70
  end
75
71
 
@@ -77,5 +73,11 @@ module Tangle
77
73
  "#<#{self.class}: #{vertices.count} vertices, #{edges.count} edges>"
78
74
  end
79
75
  alias inspect to_s
76
+
77
+ private
78
+
79
+ def callback(receiver, method, *args)
80
+ receiver.send(method, *args) if receiver.respond_to?(method)
81
+ end
80
82
  end
81
83
  end
@@ -17,15 +17,16 @@ module Tangle
17
17
  # add_edge(vtx1, vtx2, ...) => Edge
18
18
  #
19
19
  def add_edge(*vertices, **kvargs)
20
- insert_edge(self.class::Edge.new(*vertices, mixins: @mixins, **kvargs))
20
+ edge = self.class::Edge.new(*vertices, mixins: @mixins, **kvargs)
21
+ insert_edge(edge)
22
+ vertices.each { |vertex| callback(vertex, :edge_added, edge) }
23
+ edge
21
24
  end
22
25
 
23
26
  # Remove an edge from the graph
24
27
  def remove_edge(edge)
25
- edge.each_vertex do |vertex|
26
- @vertices.fetch(vertex).delete(edge)
27
- end
28
- @edges.delete(edge)
28
+ delete_edge(edge)
29
+ edge.each_vertex { |vertex| callback(vertex, :edge_removed, edge) }
29
30
  end
30
31
 
31
32
  protected
@@ -34,10 +35,12 @@ module Tangle
34
35
  #
35
36
  def insert_edge(edge)
36
37
  @edges << edge
37
- edge.each_vertex do |vertex|
38
- @vertices.fetch(vertex) << edge
39
- end
40
- edge
38
+ edge.each_vertex { |vertex| @vertices.fetch(vertex) << edge }
39
+ end
40
+
41
+ def delete_edge(edge)
42
+ edge.each_vertex { |vertex| @vertices.fetch(vertex).delete(edge) }
43
+ @edges.delete(edge)
41
44
  end
42
45
 
43
46
  private
@@ -18,12 +18,19 @@ module Tangle
18
18
  @vertices.keys
19
19
  end
20
20
 
21
+ # Select vertices in the graph
22
+ def select(&selector)
23
+ @vertices.each_key.select(&selector)
24
+ end
25
+
21
26
  # Add a vertex into the graph
22
27
  #
23
- # If a name: is given, it will be registered by name
28
+ # If a name: is given, or the vertex responds to :name,
29
+ # it will be registered by name in the graph
24
30
  def add_vertex(vertex, name: nil)
25
- @vertices[vertex] = Set[]
26
- @vertices_by_name[name] = vertex unless name.nil?
31
+ name ||= callback(vertex, :name)
32
+ insert_vertex(vertex, name)
33
+ callback(vertex, :added_to_graph, self)
27
34
  self
28
35
  end
29
36
  alias << add_vertex
@@ -33,7 +40,31 @@ module Tangle
33
40
  @vertices[vertex].each do |edge|
34
41
  remove_edge(edge) if edge.include?(vertex)
35
42
  end
43
+ delete_vertex(vertex)
44
+ callback(vertex, :removed_from_graph, self)
45
+ end
46
+
47
+ protected
48
+
49
+ def select_vertices!(selected = nil)
50
+ vertices.each do |vertex|
51
+ delete_vertex(vertex) if block_given? && !yield(vertex)
52
+ next if selected.nil?
53
+ delete_vertex(vertex) unless selected.any? { |vtx| vtx.eql?(vertex) }
54
+ end
55
+ end
56
+
57
+ def insert_vertex(vertex, name = nil)
58
+ @vertices[vertex] = Set[]
59
+ @vertices_by_name[name] = vertex unless name.nil?
60
+ end
61
+
62
+ def delete_vertex(vertex)
63
+ @vertices[vertex].each do |edge|
64
+ delete_edge(edge) if edge.include?(vertex)
65
+ end
36
66
  @vertices.delete(vertex)
67
+ @vertices_by_name.delete_if { |_, vtx| vtx.eql?(vertex) }
37
68
  end
38
69
 
39
70
  private
@@ -7,17 +7,23 @@ module Tangle
7
7
  # options are:
8
8
  # root: root directory for the structure (mandatory)
9
9
  # loaders: list of object loader lambdas (mandatory)
10
+ # ->(graph, **) { ... } => finished?
10
11
  # follow_links: bool for following symlinks to directories
11
12
  # (default false)
12
13
  #
13
- # A loader lambda will be called like
14
- # ->(graph, path, parent_path) { ... }
14
+ # A loader lambda is called with the graph as only positional
15
+ # argument, and a number of keyword arguments:
15
16
  #
16
- # The lambdas are called in order until one returns true
17
+ # path: Path of current filesystem object
18
+ # parent: Path of filesystem parent object
19
+ # lstat: File.lstat for path
20
+ # stat: File.stat for path, if lstat.symlink?
21
+ #
22
+ # The lambdas are called in order until one returns true.
17
23
  #
18
24
  # Example:
19
- # loader = lambda do |g, path, parent|
20
- # vertex = File::Stat.new(path)
25
+ # loader = lambda do |g, path:, parent:, lstat:, **|
26
+ # vertex = kwargs[:lstat]
21
27
  # g.add_vertex(vertex, name: path)
22
28
  # g.add_edge(g[parent], vertex) unless parent.nil?
23
29
  # end
@@ -38,17 +44,28 @@ module Tangle
38
44
  end
39
45
 
40
46
  def load_directory_graph(path, parent = nil)
41
- @directory_loaders.any? do |loader|
42
- loader.to_proc.call(self, path, parent)
43
- end
44
-
45
- return if File.symlink?(path) && !@follow_directory_links
46
- return unless File.directory?(path)
47
+ return unless load_directory_object(path, parent)
47
48
 
48
49
  Dir.each_child(path) do |file|
49
50
  load_directory_graph(File.join(path, file), path)
50
51
  end
51
52
  end
53
+
54
+ # Load a filesystem object into the graph, returning
55
+ # +true+ if the object was a directory (or link to one,
56
+ # and we're following links).
57
+ def load_directory_object(path, parent = nil)
58
+ stat = lstat = File.lstat(path)
59
+ stat = File.stat(path) if lstat.symlink?
60
+
61
+ @directory_loaders.any? do |loader|
62
+ loader.to_proc.call(self, path: path, parent: parent,
63
+ lstat: lstat, stat: stat)
64
+ end
65
+
66
+ return if lstat.symlink? && !@follow_directory_links
67
+ stat.directory?
68
+ end
52
69
  end
53
70
  end
54
71
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tangle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Calle Englund
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-15 00:00:00.000000000 Z
11
+ date: 2018-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git-version-bump