{"action":"created","comment":{"url":"https://api.github.com/repos/robertzk/lockbox/pulls/comments/53876045","id":53876045,"diff_hunk":"@@ -0,0 +1,510 @@\n+#' Get dependencies for all elements in lock\n+get_ordered_dependencies <- function(lock) {\n+   cat(crayon::blue(paste(\"Retrieving dependency info...\")))\n+   deps <- get_dependencies_for_list(lock, lock, list())\n+   cat(\"\\n\")\n+   deps\n+}\n+\n+#' Recursive function to take a list and lock and extract dependencies, sorting\n+#' along the way using the combine_dependencies function.\n+get_dependencies_for_list <- function(master_list, lock, previously_parsed_deps) {\n+  current_dependencies <- master_list\n+  for (i in 1:length(master_list)) {\n+    package <- master_list[[i]]\n+    previously_parsed_loc <- which_previously_parsed(\n+        package, previously_parsed_deps)\n+    if (identical(previously_parsed_loc, 0L)) {\n+      single_package_dependencies <- get_dependencies(\n+       structure(package\n+         , class = c(package$remote %||% \"CRAN\"\n+           , class(package)))\n+       , lock)\n+      previously_parsed_deps[[length(previously_parsed_deps) + 1]] <- list(\n+        package = package\n+        , dependencies = single_package_dependencies)\n+    } else {\n+      single_package_dependencies <-\n+        previously_parsed_deps[[previously_parsed_loc]]$dependencies\n+    }\n+    current_dependencies <- combine_dependencies(\n+      single_package_dependencies\n+      , current_dependencies\n+      , package$name)\n+  }\n+  if (identical(master_list, current_dependencies)) return(master_list)\n+  get_dependencies_for_list(current_dependencies, lock, previously_parsed_deps)\n+}\n+\n+#' Where, if anywhere, have I stored this packages/version combinations'\n+#' previously parsed dependencies?\n+which_previously_parsed <- function(package, previously_parsed_deps) {\n+  if (length(previously_parsed_deps) == 0) return(0L)\n+  previously_parsed_names <- vapply(previously_parsed_deps\n+    , function(p) p[[\"package\"]]$name, character(1))\n+  if (package$name %in% previously_parsed_names) {\n+    sel <- which(previously_parsed_names == package$name)\n+    subsel <- vapply(previously_parsed_deps[sel]\n+      , function(p) identical(p[[\"package\"]]$version, package$version)\n+      , logical(1))\n+    if (any(subsel)) {\n+      return(sel[subsel])\n+    }\n+  }\n+  0L\n+}\n+\n+#' Attach the latest available lockbox version to a package\n+add_latest_version_in_lockbox <- function(package) {\n+  package$latest_version_in_lockbox <- max_package_version(\n+    list.files(file.path(lockbox_library(), package)))\n+  package\n+}\n+\n+#' Take a vector of versions and find the max without coercing to package_version\n+max_package_version <- function(versions) {\n+  if (length(versions) == 0) return(NULL)\n+  formatted_versions <- package_version(as.character(versions))\n+  versions[which(formatted_versions == max(formatted_versions))[1]]\n+}\n+\n+#' Check a dependency list for inclusion in the lockfile and replace the package\n+#' with the locked version if it does appear there.  Also throw\n+#' an error if we require a dependency version greater than that specified by\n+#' the lockfile.\n+replace_with_lock <- function(package, lock) {\n+  lock_names <- vapply(lock, function(l) l$name, character(1))\n+  if (package$name %in% lock_names) {\n+    locked_package <- lock[[which(lock_names == package$name)[1]]]","path":"R/dependecies.R","position":78,"original_position":78,"commit_id":"0db497e92d2de442e1400feea9964310490937ac","original_commit_id":"0db497e92d2de442e1400feea9964310490937ac","user":{"login":"peterhurford","id":5100840,"avatar_url":"https://avatars.githubusercontent.com/u/5100840?v=3","gravatar_id":"","url":"https://api.github.com/users/peterhurford","html_url":"https://github.com/peterhurford","followers_url":"https://api.github.com/users/peterhurford/followers","following_url":"https://api.github.com/users/peterhurford/following{/other_user}","gists_url":"https://api.github.com/users/peterhurford/gists{/gist_id}","starred_url":"https://api.github.com/users/peterhurford/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/peterhurford/subscriptions","organizations_url":"https://api.github.com/users/peterhurford/orgs","repos_url":"https://api.github.com/users/peterhurford/repos","events_url":"https://api.github.com/users/peterhurford/events{/privacy}","received_events_url":"https://api.github.com/users/peterhurford/received_events","type":"User","site_admin":false},"body":"`Filter`","created_at":"2016-02-24T00:32:19Z","updated_at":"2016-02-24T00:32:19Z","html_url":"https://github.com/robertzk/lockbox/pull/73#discussion_r53876045","pull_request_url":"https://api.github.com/repos/robertzk/lockbox/pulls/73","_links":{"self":{"href":"https://api.github.com/repos/robertzk/lockbox/pulls/comments/53876045"},"html":{"href":"https://github.com/robertzk/lockbox/pull/73#discussion_r53876045"},"pull_request":{"href":"https://api.github.com/repos/robertzk/lockbox/pulls/73"}}},"pull_request":{"url":"https://api.github.com/repos/robertzk/lockbox/pulls/73","id":60424558,"html_url":"https://github.com/robertzk/lockbox/pull/73","diff_url":"https://github.com/robertzk/lockbox/pull/73.diff","patch_url":"https://github.com/robertzk/lockbox/pull/73.patch","issue_url":"https://api.github.com/repos/robertzk/lockbox/issues/73","number":73,"state":"open","locked":false,"title":"Lockbox Recursive Dependency Update","user":{"login":"davidboren","id":14277363,"avatar_url":"https://avatars.githubusercontent.com/u/14277363?v=3","gravatar_id":"","url":"https://api.github.com/users/davidboren","html_url":"https://github.com/davidboren","followers_url":"https://api.github.com/users/davidboren/followers","following_url":"https://api.github.com/users/davidboren/following{/other_user}","gists_url":"https://api.github.com/users/davidboren/gists{/gist_id}","starred_url":"https://api.github.com/users/davidboren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidboren/subscriptions","organizations_url":"https://api.github.com/users/davidboren/orgs","repos_url":"https://api.github.com/users/davidboren/repos","events_url":"https://api.github.com/users/davidboren/events{/privacy}","received_events_url":"https://api.github.com/users/davidboren/received_events","type":"User","site_admin":false},"body":"Okay!  This thing is ready for code review, though probably not merging.  Most of the relevant code is found in dependencies.R, since I've tried to minimize changes to the existing functions and files.  \r\n\r\nThis update recursively parses description files, downloading them if necessary, and sorts both dependencies and locked packages in the same list.  Dependencies are installed with locked packages in the same manner with the same function call, though dependencies will use the latest available version, only updating if packages' description file has updated it's version requirement beyond the one currently available in /.R/lockbox/  \r\n\r\nThis recursively parsed dependency information is NOT stored anywhere, but the parsing is done each time.  With a big lockfile it tends to add less than 2 seconds to startup, and certainly much less than the overall loading time.  Of course, when the packages have to be downloaded, this parsing can take longer, but still much less time than installation time.  There is some repetition of downloading here, so if we are unhappy with loading time on new package installations we can always add some additional logic to save paths to downloaded files\r\n\r\nCurrently, in the interest of leaving the original code as untouched as possible, I've left a little bit that could be dried up if combined with previous code, especially that in library.R.  The download_package.CRAN function shares some code with install_old_CRAN package, so that can be dried up if we want.\r\n\r\nI'm accessing the Remotes portion of description files as well, but final dependencies are decided based on version comparison alone, since there is no real good way to compare two different forks of the same repo.  In addition, we currently only support github remotes, since that follows from the rest of lockbox.\r\n\r\nTwo private devtools functions are currently accessed in order to save space, remote_download.github_remote and github_remote, but we can import them in explicitly if we want to be safer.  At that point, however, I might just recommend dropping the devtools dependency entirely from lockbox, since we're just downloading all the same stuff in the same way.  Then we could also lock in devtools :)  I've also stolen the tools::package.dependencies function and updated it a bit so it doesn't break and gives us remotes back (this is the biggest function in dependencies.R....I hates it but don't want to touch it any more)\r\n\r\nI've run devtools::document, so we've got a lot of extra files, but I've only altered by hand the existing files library.R, lockbox.R, and align.R (align is only changed to reduce the pesky_namespaces to lockbox's dependencies).\r\n\r\nYou'll find some logic that allows for NA versioning, which is acceptable for packages that have no version requirements.  Prior to installation they are updated with either the latest remote/CRAN version available (if we do not have the dependency or require a newer version) or the newest version in the lockbox. Some logic in lockbox.R is updated for this reason and also to distinguish, in super pretty crayon fashion, a dependency load or installation from a lockfile load or installation.\r\n\r\nFinally, you should note that it's taken me more commits to get this right than it took for RobK to write the package in the first place.  Go me!","created_at":"2016-02-23T22:50:31Z","updated_at":"2016-02-24T00:32:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f2c1bb4415c68c9696df86d4b181a39cd6d7aa57","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/robertzk/lockbox/pulls/73/commits","review_comments_url":"https://api.github.com/repos/robertzk/lockbox/pulls/73/comments","review_comment_url":"https://api.github.com/repos/robertzk/lockbox/pulls/comments{/number}","comments_url":"https://api.github.com/repos/robertzk/lockbox/issues/73/comments","statuses_url":"https://api.github.com/repos/robertzk/lockbox/statuses/0db497e92d2de442e1400feea9964310490937ac","head":{"label":"davidboren:master","ref":"master","sha":"0db497e92d2de442e1400feea9964310490937ac","user":{"login":"davidboren","id":14277363,"avatar_url":"https://avatars.githubusercontent.com/u/14277363?v=3","gravatar_id":"","url":"https://api.github.com/users/davidboren","html_url":"https://github.com/davidboren","followers_url":"https://api.github.com/users/davidboren/followers","following_url":"https://api.github.com/users/davidboren/following{/other_user}","gists_url":"https://api.github.com/users/davidboren/gists{/gist_id}","starred_url":"https://api.github.com/users/davidboren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidboren/subscriptions","organizations_url":"https://api.github.com/users/davidboren/orgs","repos_url":"https://api.github.com/users/davidboren/repos","events_url":"https://api.github.com/users/davidboren/events{/privacy}","received_events_url":"https://api.github.com/users/davidboren/received_events","type":"User","site_admin":false},"repo":{"id":51384276,"name":"lockbox","full_name":"davidboren/lockbox","owner":{"login":"davidboren","id":14277363,"avatar_url":"https://avatars.githubusercontent.com/u/14277363?v=3","gravatar_id":"","url":"https://api.github.com/users/davidboren","html_url":"https://github.com/davidboren","followers_url":"https://api.github.com/users/davidboren/followers","following_url":"https://api.github.com/users/davidboren/following{/other_user}","gists_url":"https://api.github.com/users/davidboren/gists{/gist_id}","starred_url":"https://api.github.com/users/davidboren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davidboren/subscriptions","organizations_url":"https://api.github.com/users/davidboren/orgs","repos_url":"https://api.github.com/users/davidboren/repos","events_url":"https://api.github.com/users/davidboren/events{/privacy}","received_events_url":"https://api.github.com/users/davidboren/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/davidboren/lockbox","description":"Bundler-style dependency management for R","fork":true,"url":"https://api.github.com/repos/davidboren/lockbox","forks_url":"https://api.github.com/repos/davidboren/lockbox/forks","keys_url":"https://api.github.com/repos/davidboren/lockbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/davidboren/lockbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/davidboren/lockbox/teams","hooks_url":"https://api.github.com/repos/davidboren/lockbox/hooks","issue_events_url":"https://api.github.com/repos/davidboren/lockbox/issues/events{/number}","events_url":"https://api.github.com/repos/davidboren/lockbox/events","assignees_url":"https://api.github.com/repos/davidboren/lockbox/assignees{/user}","branches_url":"https://api.github.com/repos/davidboren/lockbox/branches{/branch}","tags_url":"https://api.github.com/repos/davidboren/lockbox/tags","blobs_url":"https://api.github.com/repos/davidboren/lockbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/davidboren/lockbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/davidboren/lockbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/davidboren/lockbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/davidboren/lockbox/statuses/{sha}","languages_url":"https://api.github.com/repos/davidboren/lockbox/languages","stargazers_url":"https://api.github.com/repos/davidboren/lockbox/stargazers","contributors_url":"https://api.github.com/repos/davidboren/lockbox/contributors","subscribers_url":"https://api.github.com/repos/davidboren/lockbox/subscribers","subscription_url":"https://api.github.com/repos/davidboren/lockbox/subscription","commits_url":"https://api.github.com/repos/davidboren/lockbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/davidboren/lockbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/davidboren/lockbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/davidboren/lockbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/davidboren/lockbox/contents/{+path}","compare_url":"https://api.github.com/repos/davidboren/lockbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/davidboren/lockbox/merges","archive_url":"https://api.github.com/repos/davidboren/lockbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/davidboren/lockbox/downloads","issues_url":"https://api.github.com/repos/davidboren/lockbox/issues{/number}","pulls_url":"https://api.github.com/repos/davidboren/lockbox/pulls{/number}","milestones_url":"https://api.github.com/repos/davidboren/lockbox/milestones{/number}","notifications_url":"https://api.github.com/repos/davidboren/lockbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/davidboren/lockbox/labels{/name}","releases_url":"https://api.github.com/repos/davidboren/lockbox/releases{/id}","deployments_url":"https://api.github.com/repos/davidboren/lockbox/deployments","created_at":"2016-02-09T17:30:05Z","updated_at":"2016-02-09T17:30:05Z","pushed_at":"2016-02-23T22:56:50Z","git_url":"git://github.com/davidboren/lockbox.git","ssh_url":"git@github.com:davidboren/lockbox.git","clone_url":"https://github.com/davidboren/lockbox.git","svn_url":"https://github.com/davidboren/lockbox","homepage":null,"size":493,"stargazers_count":0,"watchers_count":0,"language":"R","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"robertzk:master","ref":"master","sha":"d3331227a1bd421cbf98c21268b9cdfa7a81fa94","user":{"login":"robertzk","id":1638492,"avatar_url":"https://avatars.githubusercontent.com/u/1638492?v=3","gravatar_id":"","url":"https://api.github.com/users/robertzk","html_url":"https://github.com/robertzk","followers_url":"https://api.github.com/users/robertzk/followers","following_url":"https://api.github.com/users/robertzk/following{/other_user}","gists_url":"https://api.github.com/users/robertzk/gists{/gist_id}","starred_url":"https://api.github.com/users/robertzk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robertzk/subscriptions","organizations_url":"https://api.github.com/users/robertzk/orgs","repos_url":"https://api.github.com/users/robertzk/repos","events_url":"https://api.github.com/users/robertzk/events{/privacy}","received_events_url":"https://api.github.com/users/robertzk/received_events","type":"User","site_admin":false},"repo":{"id":33389821,"name":"lockbox","full_name":"robertzk/lockbox","owner":{"login":"robertzk","id":1638492,"avatar_url":"https://avatars.githubusercontent.com/u/1638492?v=3","gravatar_id":"","url":"https://api.github.com/users/robertzk","html_url":"https://github.com/robertzk","followers_url":"https://api.github.com/users/robertzk/followers","following_url":"https://api.github.com/users/robertzk/following{/other_user}","gists_url":"https://api.github.com/users/robertzk/gists{/gist_id}","starred_url":"https://api.github.com/users/robertzk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/robertzk/subscriptions","organizations_url":"https://api.github.com/users/robertzk/orgs","repos_url":"https://api.github.com/users/robertzk/repos","events_url":"https://api.github.com/users/robertzk/events{/privacy}","received_events_url":"https://api.github.com/users/robertzk/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/robertzk/lockbox","description":"Bundler-style dependency management for R","fork":false,"url":"https://api.github.com/repos/robertzk/lockbox","forks_url":"https://api.github.com/repos/robertzk/lockbox/forks","keys_url":"https://api.github.com/repos/robertzk/lockbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/robertzk/lockbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/robertzk/lockbox/teams","hooks_url":"https://api.github.com/repos/robertzk/lockbox/hooks","issue_events_url":"https://api.github.com/repos/robertzk/lockbox/issues/events{/number}","events_url":"https://api.github.com/repos/robertzk/lockbox/events","assignees_url":"https://api.github.com/repos/robertzk/lockbox/assignees{/user}","branches_url":"https://api.github.com/repos/robertzk/lockbox/branches{/branch}","tags_url":"https://api.github.com/repos/robertzk/lockbox/tags","blobs_url":"https://api.github.com/repos/robertzk/lockbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/robertzk/lockbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/robertzk/lockbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/robertzk/lockbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/robertzk/lockbox/statuses/{sha}","languages_url":"https://api.github.com/repos/robertzk/lockbox/languages","stargazers_url":"https://api.github.com/repos/robertzk/lockbox/stargazers","contributors_url":"https://api.github.com/repos/robertzk/lockbox/contributors","subscribers_url":"https://api.github.com/repos/robertzk/lockbox/subscribers","subscription_url":"https://api.github.com/repos/robertzk/lockbox/subscription","commits_url":"https://api.github.com/repos/robertzk/lockbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/robertzk/lockbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/robertzk/lockbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/robertzk/lockbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/robertzk/lockbox/contents/{+path}","compare_url":"https://api.github.com/repos/robertzk/lockbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/robertzk/lockbox/merges","archive_url":"https://api.github.com/repos/robertzk/lockbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/robertzk/lockbox/downloads","issues_url":"https://api.github.com/repos/robertzk/lockbox/issues{/number}","pulls_url":"https://api.github.com/repos/robertzk/lockbox/pulls{/number}","milestones_url":"https://api.github.com/repos/robertzk/lockbox/milestones{/number}","notifications_url":"https://api.github.com/repos/robertzk/lockbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/robertzk/lockbox/labels{/name}","releases_url":"https://api.github.com/repos/robertzk/lockbox/releases{/id}","deployments_url":"https://api.github.com/repos/robertzk/lockbox/deployments","created_at":"2015-04-04T01:07:35Z","updated_at":"2015-05-04T17:40:07Z","pushed_at":"2016-02-23T22:56:51Z","git_url":"git://github.com/robertzk/lockbox.git","ssh_url":"git@github.com:robertzk/lockbox.git","clone_url":"https://github.com/robertzk/lockbox.git","svn_url":"https://github.com/robertzk/lockbox","homepage":null,"size":260,"stargazers_count":8,"watchers_count":8,"language":"R","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":3,"mirror_url":null,"open_issues_count":24,"forks":3,"open_issues":24,"watchers":8,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/robertzk/lockbox/pulls/73"},"html":{"href":"https://github.com/robertzk/lockbox/pull/73"},"issue":{"href":"https://api.github.com/repos/robertzk/lockbox/issues/73"},"comments":{"href":"https://api.github.com/repos/robertzk/lockbox/issues/73/comments"},"review_comments":{"href":"https://api.github.com/repos/robertzk/lockbox/pulls/73/comments"},"review_comment":{"href":"https://api.github.com/repos/robertzk/lockbox/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/robertzk/lockbox/pulls/73/commits"},"statuses":{"href":"https://api.github.com/repos/robertzk/lockbox/statuses/0db497e92d2de442e1400feea9964310490937ac"}}}}