Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion R/versions.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
##
## ----------------------------------------------------------------------

pkg_graph_version <- "0.8.0"
pkg_graph_version <- "1.5.0"

pkg_graph_version_obj <- as.package_version(pkg_graph_version)

Expand Down Expand Up @@ -96,7 +96,20 @@ upgrade_graph <- function(graph) {
if (g_ver == "0.4.0") {
.Call(R_igraph_add_env, graph)
} else if (g_ver == "0.7.999") {
# Not observed in the wild
.Call(R_igraph_add_myid_to_env, graph)
.Call(R_igraph_add_version_to_env, graph)
} else if (g_ver == "0.8.0") {
.Call(R_igraph_add_version_to_env, graph)
graph <- unclass(graph)
graph[igraph_t_idx_oi:igraph_t_idx_is] <- list(NULL)
class(graph) <- "igraph"

# Calling for side effect: error if R_SEXP_to_igraph() fails, create native igraph,
# update "me" element of environment
V(graph)

graph
} else {
stop("Don't know how to upgrade graph from ", g_ver, " to ", p_ver)
}
Expand All @@ -122,6 +135,17 @@ warn_version <- function(graph) {
" Call upgrade_graph() on it to use with the current igraph version\n",
" For now we convert it on the fly..."
)

# In-place upgrade:
# - The igraph element in the igraph_t_idx_env component will be added
# transparently because it's missing.
# - The components igraph_t_idx_oi, igraph_t_idx_ii, igraph_t_idx_os,
# igraph_t_idx_is are ignored, but we can't do much about the contents.
# Users will have to call upgrade_graph(), but this is what the message
# is about.
if (pkg_graph_version <= "1.5.0") {
.Call(R_igraph_add_version_to_env, graph)
}
return(TRUE)
}

Expand Down Expand Up @@ -149,3 +173,9 @@ oldsamples <- function() {
"0.1.1" = oldsample_0_1_1()
)
}

clear_native_ptr <- function(g) {
gx <- unclass(g)
gx[[igraph_t_idx_env]]$igraph <- NULL
g
}
2 changes: 2 additions & 0 deletions src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extern "C" {
/* .Call calls */
extern SEXP R_igraph_add_edges(SEXP, SEXP);
extern SEXP R_igraph_add_env(SEXP);
extern SEXP R_igraph_add_myid_to_env(SEXP);
extern SEXP R_igraph_add_version_to_env(SEXP);
extern SEXP R_igraph_add_vertices(SEXP, SEXP);
extern SEXP R_igraph_address(SEXP);
Expand Down Expand Up @@ -398,6 +399,7 @@ extern SEXP promise_expr_(SEXP);
static const R_CallMethodDef CallEntries[] = {
{"R_igraph_add_edges", (DL_FUNC) &R_igraph_add_edges, 2},
{"R_igraph_add_env", (DL_FUNC) &R_igraph_add_env, 1},
{"R_igraph_add_myid_to_env", (DL_FUNC) &R_igraph_add_myid_to_env, 1},
{"R_igraph_add_version_to_env", (DL_FUNC) &R_igraph_add_version_to_env, 1},
{"R_igraph_add_vertices", (DL_FUNC) &R_igraph_add_vertices, 2},
{"R_igraph_address", (DL_FUNC) &R_igraph_address, 1},
Expand Down
2 changes: 1 addition & 1 deletion src/rinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

#include "uuid/uuid.h"

#define R_IGRAPH_TYPE_VERSION "0.8.0"
#define R_IGRAPH_TYPE_VERSION "1.5.0"
#define R_IGRAPH_VERSION_VAR ".__igraph_version__."

SEXP R_igraph_add_env(SEXP graph);
Expand Down
21 changes: 14 additions & 7 deletions src/rinterface_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -2986,6 +2986,9 @@ void R_igraph_restore_pointer(SEXP graph) {

igraph_t *R_igraph_get_pointer(SEXP graph) {
if (GET_LENGTH(graph) != igraph_t_idx_max || !Rf_isEnvironment(R_igraph_graph_env(graph))) {
if (GET_LENGTH(graph) == 11) {
Rf_error("This graph was created by igraph < 0.2.\n Upgrading this format is not supported, sorry.");
}
Rf_error("This graph was created by a now unsupported old igraph version.\n Call upgrade_version() before using igraph functions on that object.");
}

Expand Down Expand Up @@ -9945,7 +9948,9 @@ SEXP R_igraph_identical_graphs(SEXP g1, SEXP g2, SEXP attrs) {
}

SEXP R_igraph_graph_version(SEXP graph) {
if (GET_LENGTH(graph) == igraph_t_idx_max && Rf_isEnvironment(R_igraph_graph_env(graph))) {
if (GET_LENGTH(graph) == 11) {
return Rf_mkString("0.1.1");
} else if (GET_LENGTH(graph) == igraph_t_idx_max && Rf_isEnvironment(R_igraph_graph_env(graph))) {
SEXP ver = Rf_findVar(Rf_install(R_IGRAPH_VERSION_VAR), R_igraph_graph_env(graph));
if (ver != R_UnboundValue) {
return ver;
Expand All @@ -9957,24 +9962,26 @@ SEXP R_igraph_graph_version(SEXP graph) {
}
}

SEXP R_igraph_add_version_to_env(SEXP graph) {
SEXP R_igraph_add_myid_to_env(SEXP graph) {
uuid_t my_id;
char my_id_chr[40];

PROTECT(graph = Rf_duplicate(graph));

uuid_generate(my_id);
uuid_unparse_lower(my_id, my_id_chr);
SEXP l1 = PROTECT(Rf_install("myid"));
SEXP l2 = PROTECT(Rf_mkString(my_id_chr));
Rf_defineVar(l1, l2, R_igraph_graph_env(graph));
UNPROTECT(2);
l1 = PROTECT(Rf_install(R_IGRAPH_VERSION_VAR));
l2 = PROTECT(Rf_mkString(R_IGRAPH_TYPE_VERSION));

return graph;
}

SEXP R_igraph_add_version_to_env(SEXP graph) {
SEXP l1 = PROTECT(Rf_install(R_IGRAPH_VERSION_VAR));
SEXP l2 = PROTECT(Rf_mkString(R_IGRAPH_TYPE_VERSION));
Rf_defineVar(l1, l2, R_igraph_graph_env(graph));
UNPROTECT(2);

UNPROTECT(1);
return graph;
}

Expand Down
77 changes: 73 additions & 4 deletions tests/testthat/_snaps/versions.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,73 @@
# reading of old igraph formats
# we can't upgrade from 0.1.1 to 1.5.0, on the fly

Code
s[["0.1.1"]]
oldsample_0_1_1()
Error <simpleError>
This graph was created by igraph < 0.2.
Upgrading this format is not supported, sorry.

# we can't upgrade from 0.1.1 to 1.5.0, explicitly

Code
upgrade_graph(g)
Error <simpleError>
Don't know how to upgrade graph from 0.1.1 to 1.5.0

# we can't upgrade from 0.2 to 1.5.0, on the fly

Code
oldsample_0_2()
Error <simpleError>
This graph was created by a now unsupported old igraph version.
Call upgrade_version() before using igraph functions on that object.

# we can't upgrade from 0.5 to 1.5.0, on the fly

Code
oldsample_0_5()
Error <simpleError>
This graph was created by a now unsupported old igraph version.
Call upgrade_version() before using igraph functions on that object.

# we can't upgrade from 0.6 to 1.5.0, on the fly

Code
oldsample_0_6()
Error <simpleError>
This graph was created by a now unsupported old igraph version.
Call upgrade_version() before using igraph functions on that object.

# we can upgrade from 1.0.0 to 1.5.0, on the fly

Code
g <- oldsample_1_0_0()
graph_version(g)
Output
[1] '0.8.0'
Code
g
Message <simpleMessage>
This graph was created by an old(er) igraph version.
Call upgrade_graph() on it to use with the current igraph version
For now we convert it on the fly...
Output
IGRAPH D--- 3 3 -- Ring graph
+ attr: name (g/c), mutual (g/l), circular (g/l), bar (v/c), foo (e/c)
+ edges:
[1] 1->2 2->3 3->1
Code
graph_version(g)
Output
[1] '1.5.0'

# reading of old igraph formats

Code
s[["0.1.1"]]
Error <simpleError>
This graph was created by igraph < 0.2.
Upgrading this format is not supported, sorry.

---

Code
Expand Down Expand Up @@ -34,6 +96,10 @@

Code
s[["1.0.0"]]
Message <simpleMessage>
This graph was created by an old(er) igraph version.
Call upgrade_graph() on it to use with the current igraph version
For now we convert it on the fly...
Output
IGRAPH D--- 3 3 -- Ring graph
+ attr: name (g/c), mutual (g/l), circular (g/l), bar (v/c), foo (e/c)
Expand All @@ -44,6 +110,9 @@

Code
s[["1.5.0"]]
Error <simpleError>
This graph was created by a new(er) igraph version. Please install the latest version of igraph and try again.
Output
IGRAPH D--- 3 3 -- Ring graph
+ attr: name (g/c), mutual (g/l), circular (g/l), bar (v/c), foo (e/c)
+ edges:
[1] 1->2 2->3 3->1

88 changes: 81 additions & 7 deletions tests/testthat/test-versions.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,90 @@ test_that("we create graphs of the current version", {
expect_equal(v1, v2)
})

test_that("we can upgrade from 0.4.0 to 0.8.0", {
g <- make_ring(10)
g <- unclass(g)
g[[10]] <- NULL
class(g) <- "igraph"
test_that("we can't upgrade from 0.1.1 to 1.5.0, on the fly", {
expect_snapshot(error = TRUE, {
oldsample_0_1_1()
})
})

test_that("we can't upgrade from 0.1.1 to 1.5.0, explicitly", {
g <- oldsample_0_1_1()

expect_equal(graph_version(g), as.package_version("0.1.1"))

expect_snapshot(error = TRUE, {
upgrade_graph(g)
})
})

test_that("we can't upgrade from 0.2 to 1.5.0, on the fly", {
expect_snapshot(error = TRUE, {
oldsample_0_2()
})
})

test_that("we can upgrade from 0.2 to 1.5.0, explicitly", {
g <- oldsample_0_2()

expect_equal(graph_version(g), as.package_version("0.4.0"))

g2 <- upgrade_graph(g)
expect_equal(graph_version(g2), as.package_version("1.5.0"))
})

test_that("we can't upgrade from 0.5 to 1.5.0, on the fly", {
expect_snapshot(error = TRUE, {
oldsample_0_5()
})
})

test_that("we can upgrade from 0.5 to 1.5.0, explicitly", {
g <- oldsample_0_5()

expect_equal(graph_version(g), as.package_version("0.4.0"))

g2 <- upgrade_graph(g)
expect_equal(graph_version(g2), as.package_version("1.5.0"))
})

test_that("we can't upgrade from 0.6 to 1.5.0, on the fly", {
expect_snapshot(error = TRUE, {
oldsample_0_6()
})
})

test_that("we can upgrade from 0.6 to 1.5.0, explicitly", {
g <- oldsample_0_6()

expect_equal(graph_version(g), as.package_version("0.4.0"))

g2 <- upgrade_graph(g)
expect_equal(graph_version(g2), as.package_version("0.8.0"))
expect_equal(graph_version(g2), as.package_version("1.5.0"))
})

test_that("we can upgrade from 1.0.0 to 1.5.0, on the fly", {
local_igraph_options(print.id = FALSE)

expect_snapshot({
g <- oldsample_1_0_0()
graph_version(g)
g
graph_version(g)
})
})

test_that("we can upgrade from 1.0.0 to 1.5.0, explicitly", {
g <- oldsample_1_0_0()
graph_version(g)
g2 <- upgrade_graph(g)
graph_version(g2)

g3 <- oldsample_1_5_0()

expect_identical(
unclass(clear_native_ptr(g2)),
unclass(clear_native_ptr(g3))
)
})

test_that("reading of old igraph formats", {
Expand All @@ -36,7 +110,7 @@ test_that("reading of old igraph formats", {
expect_snapshot({
s[["1.0.0"]]
})
expect_snapshot(error = TRUE, {
expect_snapshot({
s[["1.5.0"]]
})
})