aboutsummaryrefslogtreecommitdiff
path: root/doc/bugs/transitive_dependencies.mdwn
blob: b073f190bb66a8e081f784fb246b88c8750e628a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
If a sidebar contains a map, or inline (etc), one would expect a
change/add/remove of any of the mapped/inlined pages to cause a full wiki
rebuild. But this does not happen.

If page A inlines page B, which inlines page C, a change to C will cause B
to be updated, but A will not "notice" that this means A needs to be
updated.

One way to look at this bug is that it's a bug in where dependencies are
recorded when preprocessing the rendered or sidebar page. The current code
does:

	add_depends($params{page}, $somepage);

Where `$params{page}` is page B. If this is changed to `$params{destpage}`,
then the dependency is added to page A, and updates to C cause it to
change. This does result in the page A's getting lots more dependency info
recorded than before (essentially a copy of all the B's dependency info).

It's also a fragile, since all plugins that handle dependencies have to be
changed, and do this going forward. And it seems non-obvious that this should
be done. Or really, whether to use `page` or `destpage` there. Currently,
making the "wrong" choice and using `destpage` instead of `page` (which nearly
everything uses) will just result in semi-redundant dependency info being
recorded. If we make destpage mandatory to fix this, goofing up will lead to
this bug coming back. Ugh.

----

## rebuild = change approach

[[!template id=gitbranch branch=origin/transitive-dependencies author="[[joey]]"]]

Another approach to fix it is to say that anything that causes a
rebuild of B is treated as a change of B. Then when C is changed, B is
rebuilt due to dependencies, and in turn this means A is rebuilt because B
"changed". 

This is essentially what is done with wikilinks now, and why, if a sidebar
links to page C, add/remove of C causes all pages to be rebuilt, as seen 
here:

	removing old page meep
	building sidebar.mdwn, which links to meep
	building TourBusStop.mdwn, which depends on sidebar
	building contact.mdwn, which depends on sidebar
	...

Downsides here:

* Means a minimum of 2x as much time spent resolving dependencies,
  at least in my simple implementation, which re-runs the dependency
  resolution loop until no new pages are rebuilt.
  (I added an optimisation that gets it down to 1.5X as much work on
  average, still 2x as much worst case. I suppose building a directed
  graph and traversing it would be theoretically more efficient.)
* Causes extra work for some transitive dependencies that we don't
  actually care about. For example, changing index causes
  plugins/brokenlinks to update in the first pass; if there's a second
  pass, plugins/map is then updated, because it depends on plugins/brokenlinks.
  (Of course, this is just a special case of the issue that a real
  modification to plugins/brokenlinks causes an unnecessary update of plugins/map,
  because we have [[only_one_kind_of_dependency|todo/dependency_types]].)
  (Fixed now for cases like this one where contenless dependencies avoid
  the unnecessary work.)

--[[Joey]]