Isn't it possible to compile knitr document from nested child? - nested

I tried to make 2 stage nested child where I referred the main document as the first stage child. If I compile it from the first stage child, it works fine however when I tried to compile from the second stage child it stopped. I think their should be some indication in the second stage child for its main-main document in base stage.
The file structure is like,
Main.Rnw
- FirstStage.Rnw
- SecondStage.Rnw
At the top of FirstStage.Rnw, I wrote: % !Rnw root = path/to/Main.Rnw
At the top of SecondStage.Rnw, I wrote: % !Rnw root = path/to/FirstStage.Rnw

Related

Gradle script execution semantics

I am trying to understand how exactly is the following Gradle script executed:
task loadTestData(dependsOn: ['fakeTask', createSchema])
I assume that:
loadTestData is a method call
dependsOn is a named argument
But on which object is the method called?
Actually a Task is being executed as part of gradle build workflow. Tasks in gradle get no parameters but can operate on the system/environment/build variables.
Then dependsOn which is a property of the Task gets the tasks the declared defined task is dependent on.
In this case you declare that task loadTestData is dependent on tasks fakeTask and createSchema.

Grade: Can't access configuration defined in one project from another project

I'm pretty new to both gradle and groovy.
The Problem
I've got a very simple multi-project structure just like below:
Root project 'gradle_test'
+--- Project ':sub1'
\--- Project ':sub2'
This is what the 'build.grade' file looks like for sub1 project:
// build.gradle of sub1 project
task testConfiguration {
println project(':sub2').configurations.sub2FooConfiguration
}
And finally, this is the 'build.grade' file of sub2 project:
// build.gradle of sub2 project
configurations {
sub2FooConfiguration
}
Very minimum. Now, if I run gradle :sub1:testConfiguration, I got the following error:
A problem occurred evaluating project ':sub1'.
> Could not find property 'sub2FooConfiguration' on configuration container.
However, everything just works if the testConfiguration task in sub1 project is modified like this:
// notice the "<<" (I believe this is calling the 'doLast' method on the task instance)
task testConfiguration << {
println project(':sub2').configurations.sub2FooConfiguration
}
The Question
What I assume the difference between the two versions of the 'testConfiguration' task is that in the first instance, a configuration closure is passed to the task whereas in the modified version a 'normal' closure is passed to the 'doLast' method.
So, first of all, is my assumption correct?
Secondly, why I don't have access to 'sub2' project in the first instance?
And finally, is it possible to access 'sub2' project in the first instance (i.e. in the configuration closure)?
[Update] A Further Question
Given the accepted answer provided by "Invisible Arrow", I'd like to ask a further question regarding the best practice of referencing a configuration of another project (i.e. a task in sub1 needs to use an archive produced by sub2 project).
Should I declare evaluation dependency between the two projects?
Or Should I only reference sub2's configuration at execution time (e.g. in doLast())?
Or, should I create a dependency configuration between the two projects?
Yes, there is a difference between the two.
There are essentially 3 phases to a build which are Initialization, Configuration and Execution. This is described in detail under the Build Lifecycle chapter in the Gradle documentation.
In your case, the first instance falls under the Configuration phase, which is always evaluated irrespective of whether the task is executed or not. That means all statements within the closure are executed when you start a build.
task testConfiguration {
// This always runs during a build,
// irrespective of whether the task is executed or not
println project(':sub2').configurations.sub2FooConfiguration
}
The second instance falls under the Execution phase. Note that << is a shorthand for doLast, and this closure is called when the task is executed.
task testConfiguration << {
// Called during actual execution of the task,
// and called only if the task was scheduled to be executed.
// Note that Configuration phase for both projects are complete at this point,
// which is why :sub1 is able to access :sub2's configurations.sub2FooConfiguration
println project(':sub2').configurations.sub2FooConfiguration
}
Now coming to why the first instance gave the error. This was because the Configuration phase of sub2 project was not evaluated yet. Hence the sub2FooConfiguration wasn't yet created.
Why? Because there is no explicit evaluation dependency between sub1 and sub2. In your case, sub1 needs sub2 as an evaluation dependency, hence we can add that dependency in sub1's build.gradle before the task declaration, as follows:
evaluationDependsOn(':sub2')
task testConfiguration {
println project(':sub2').configurations.sub2FooConfiguration
}
This will ensure that sub2 is always evaluated before sub1 (evaluation meaning the Configuration phase for the projects). sub1 will now be able to access configurations.sub2FooConfiguration in the task declaration closure. This is explained in detail in the Multi-project Builds chapter.
In the second instance, configurations.sub2FooConfiguration was accessible, as the call was in the execution block of the task (which is after the Configuration phase for both projects).
PS: Note that if you reversed the names of the projects, then the first instance might actually work, as Gradle configures projects alphabetically if there are no explicit dependencies. But, of course, you should never rely on this and ensure that the dependencies between projects are declared explicitly.

Aggregate tasks in Gradle

I'm working on a gradle task that depends on other gradle tasks, i.e an aggregate task. The aggregate task required the other tasks to run in a certain linear order too.
Note: The other tasks must be able to run in isolation. The dependencies between the tasks ONLY makes sense when running the aggregate task.
My first attempt was to use someTask.execute(), but then I realized that this was not the Gradle way, i.e it is not a supported feature and that the internal API might change.
task aggregate() {
doFirst {
// Need to set properties required by other tasks
project.ext.somePropRequiredByTask1 = propertyX + "-" propertyY
}
doLast {
task1.execute()
task2.execute()
task3.execute()
}
}
After reading up on creating aggregate tasks, this is my current solution:
task aggregate() {
// Only configure task if the task is exlicitly run
if (gradle.startParamter.taskNames.contains("aggregate") {
project.ext.somePropRequiredByTask1 = propertyX + "-" propertyY
chainTaskDependencies([task1, task2, task3])
}
}
// Create a strict dependsOn dependency order for the tasks in the task list
def chainTaskDependencies(List<Task> tasks) {
def taskNames = tasks.collect { it.name}
println "Run tasks in this order: " taskNames.join " -> "
def reversed = tasks.reverse()
for (int i = 0; i< reversed.size() -1 ; i ++) {
reversed[i].dependsOn(reversed[i+1])
}
}
Is this the correct way to create an aggregate task dependency where the order between tasks is linear? How can it be improved?
How about just extracting shutdownVM, waitForVMShutdown and rollback to functions/closures that your tasks call ? Then you are free to compose them in any which way you choose.
I've found this to be the most flexible option in similar cases.
B.mustRunAfter(A)
means that if both A and B run then B must run after A. B can be run by itself no problems.
So:
task A
task B
task C
task aggregate(dependsOn(['A', 'B', 'C'])
C.mustRunAfter(B)
B.mustRunAfter(A)
As Gradle team member and Spock inventor Peter Neiderweiser puts it here:
You can't, because a task (instance) will be executed at most once per build. Instead, the way to go is to declare multiple task instances. You could do this by putting the task declaration in a loop, putting it in a method and calling it multiple times, or by writing a task class and instantiating it multiple times. Then you'll add one other task that depends on all bulk tasks. Assuming the execution order between bulk tasks is irrelevant, that's it.
He also suggests using task rules for this purpose.
The OP also posts the solution he or she devised, so you can look at that as well.

How to set a relationship from one NSManageObject to another in a different NSManagedObjectContext

Because my app is multi-threaded I use two NSManagedObjectContexts. The main context, that runs in the main thread and another context that only runs in a separate thread.
I have created a small test app. It has two Core Data Entities. Parent and Child. Parent has a one-to-many relationship to Child. Child has a 1-1 relationship to Parent.
In one test method (that runs in a separate thread) I get a Parent instance, that has been created during a run time before. So it's in the main context. I get this parent with this line of code:
Parent *tmpParent = [[parentController selectedObjects] objectAtIndex:0];
Then I create some children in the thread-context (managedObjectContextInBackground), set their parent to the tmpParent, give them a name and save the thread-context:
Child *child1 = (Child *)[NSEntityDescription insertNewObjectForEntityForName:#"Child" inManagedObjectContext:managedObjectContextInBackground];
[child1 setName:#"Homer"];
[child1 setParent:tmpParent];
Child *child2 = (Child *)[NSEntityDescription insertNewObjectForEntityForName:#"Child" inManagedObjectContext:managedObjectContextInBackground];
[child2 setName:#"Wilma"];
[child2 setParent:tmpParent];
[self saveManagedObjectContextInBackground];
If I execute that method the application crashes and says:
Illegal attempt to establish a relationship 'parent' between objects in different contexts
That's why I added this line below the tmpParent declaration:
[managedObjectContextInBackground insertObject:tmpParent];
But, the application crashes again saying:
An NSManagedObject may only be in (or observed by) a single NSManagedObjectContext
I looked through the documentation, but I couldn't find a way to solve this problem.
Question: How can I set the relationship of Child to Parent, when Parent is in a different NSManagedObjectContext, than Child ??
Your object can be loaded from another context, thus, when you create a new NSManagedObject in your other thread, nothing stops you from fetching an existing NSManagedObject which may or may not be being used in the main thread, and use that reference in order to set up your relationship.
When you exit the thread and merge the contexts, this change will get updated for the object that was until this point happily existing in memory on the main thread.

NSFetchResults update delegate works first time, crashes second time

I've looked around SO for similar answers, but my issue seems a litte different.
I have a UITableView that is tied to a NSFetchResultsController. The goal is to pull up some data, add a couple rows into the Context, and the table is automatically updated. Simple, right?
init -> empty table -> performFetch -> create some objects in the Context -> delegate sees this and updates my table.
I'm using the boilerplate NSFetchResultsController for noticing when the current context has been modified.
When I run this with a clean Simulator/iOS platform, the NSFetchController successfully recognizes that data in the Context has been updated. But if I run the app a second time, I get the following error:
CoreData: error: Serious application error. Exception was caught during Core Data change
processing. This is usually a bug within an observer of
NSManagedObjectContextObjectsDidChangeNotification. *** -[__NSArrayI objectAtIndex:]:
index 40 beyond bounds for empty array with userInfo (null)
The crash occurs on calling [self.tableView beginUpdates];
In my debugging I can see that '[fetchedResultsController fetchedObjects]' is completely empty and I think thats the problem - shouldn't this be updating with my test data since I modified the context? I'm using the Apple Recipe and CoreDataBooks examples as reference.
I think this is because you Data Modle in class just not fit the entity in you .xcdatamodeld file.

Resources