Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
A
apk-tools
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Hassan Albahri
apk-tools
Commits
55b7b89e
Commit
55b7b89e
authored
15 years ago
by
Timo Teräs
Browse files
Options
Downloads
Patches
Plain Diff
state: auto clean packages
Automatically remove packages that are no longer required by a top level dependency.
parent
a9b6d18f
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/state.c
+164
-45
164 additions, 45 deletions
src/state.c
with
164 additions
and
45 deletions
src/state.c
+
164
−
45
View file @
55b7b89e
...
...
@@ -170,16 +170,8 @@ int apk_state_lock_dependency(struct apk_state *state,
return
-
1
;
if
(
ns_empty
(
state
->
name
[
name
->
id
]))
{
if
(
dep
->
result_mask
==
APK_DEPMASK_CONFLICT
)
{
if
((
name
->
flags
&
APK_NAME_TOPLEVEL
)
&&
!
(
apk_flags
&
APK_FORCE
))
{
apk_error
(
"Not deleting top level dependency "
"'%s'. Use -f to override."
,
name
->
name
);
return
-
1
;
}
if
(
dep
->
result_mask
==
APK_DEPMASK_CONFLICT
)
return
apk_state_lock_name
(
state
,
name
,
NULL
);
}
/* This name has not been visited yet.
* Construct list of candidates. */
...
...
@@ -284,16 +276,126 @@ static int apk_state_fix_package(struct apk_state *state,
return
0
;
}
static
int
call_if_dependency_broke
(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
,
struct
apk_name
*
dep_name
,
int
(
*
cb
)(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
))
{
struct
apk_package
*
dep_pkg
;
int
k
;
if
(
pkg
->
depends
==
NULL
)
return
0
;
dep_pkg
=
ns_to_pkg
(
state
->
name
[
dep_name
->
id
]);
for
(
k
=
0
;
k
<
pkg
->
depends
->
num
;
k
++
)
{
struct
apk_dependency
*
dep
=
&
pkg
->
depends
->
item
[
k
];
if
(
dep
->
name
!=
dep_name
)
continue
;
if
(
dep_pkg
==
NULL
&&
dep
->
result_mask
==
APK_DEPMASK_CONFLICT
)
continue
;
if
(
dep_pkg
!=
NULL
&&
(
apk_version_compare
(
APK_BLOB_STR
(
dep_pkg
->
version
),
APK_BLOB_STR
(
dep
->
version
))
&
dep
->
result_mask
))
continue
;
return
cb
(
state
,
pkg
);
}
return
0
;
}
static
int
for_each_broken_reverse_depency
(
struct
apk_state
*
state
,
struct
apk_name
*
name
,
int
(
*
cb
)(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
))
{
struct
apk_package
*
pkg0
;
int
i
,
j
,
r
;
if
(
name
->
rdepends
==
NULL
)
return
0
;
for
(
i
=
0
;
i
<
name
->
rdepends
->
num
;
i
++
)
{
struct
apk_name
*
name0
=
name
->
rdepends
->
item
[
i
];
if
(
ns_locked
(
state
->
name
[
name0
->
id
]))
{
pkg0
=
ns_to_pkg
(
state
->
name
[
name0
->
id
]);
if
(
pkg0
==
NULL
)
continue
;
return
call_if_dependency_broke
(
state
,
pkg0
,
name
,
cb
);
}
if
(
!
ns_empty
(
state
->
name
[
name0
->
id
]))
{
struct
apk_name_choices
*
ns
=
ns_to_choices
(
state
->
name
[
name0
->
id
]);
for
(
j
=
0
;
j
<
ns
->
num
;
j
++
)
{
if
(
apk_pkg_get_state
(
ns
->
pkgs
[
j
])
!=
APK_PKG_INSTALLED
)
continue
;
r
=
call_if_dependency_broke
(
state
,
ns
->
pkgs
[
j
],
name
,
cb
);
if
(
r
!=
0
)
return
r
;
}
return
0
;
}
for
(
j
=
0
;
j
<
name0
->
pkgs
->
num
;
j
++
)
{
pkg0
=
name0
->
pkgs
->
item
[
j
];
if
(
apk_pkg_get_state
(
pkg0
)
!=
APK_PKG_INSTALLED
)
continue
;
r
=
call_if_dependency_broke
(
state
,
name0
->
pkgs
->
item
[
j
],
name
,
cb
);
if
(
r
!=
0
)
return
r
;
}
}
return
0
;
}
static
int
delete_broken_package
(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
)
{
return
apk_state_lock_name
(
state
,
pkg
->
name
,
NULL
);
}
static
int
reinstall_broken_package
(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
)
{
struct
apk_dependency
dep
=
{
.
name
=
pkg
->
name
,
.
result_mask
=
APK_DEPMASK_REQUIRE
,
};
return
apk_state_lock_dependency
(
state
,
&
dep
);
}
int
apk_state_lock_name
(
struct
apk_state
*
state
,
struct
apk_name
*
name
,
struct
apk_package
*
newpkg
)
{
struct
apk_package
*
oldpkg
=
NULL
;
int
i
,
j
,
k
,
r
;
int
i
,
r
;
if
(
name
->
id
>=
state
->
num_names
)
return
-
1
;
if
((
name
->
flags
&
APK_NAME_TOPLEVEL
)
&&
!
(
apk_flags
&
APK_FORCE
))
{
apk_error
(
"Not deleting top level dependency '%s'. "
"Use -f to override."
,
name
->
name
);
return
-
1
;
}
ns_free
(
state
->
name
[
name
->
id
]);
state
->
name
[
name
->
id
]
=
ns_from_pkg
(
newpkg
);
...
...
@@ -302,7 +404,8 @@ int apk_state_lock_name(struct apk_state *state,
struct
apk_package
*
pkg
=
name
->
pkgs
->
item
[
i
];
if
(
name
->
pkgs
->
item
[
i
]
->
name
==
name
&&
apk_pkg_get_state
(
name
->
pkgs
->
item
[
i
])
==
APK_PKG_INSTALLED
)
apk_pkg_get_state
(
name
->
pkgs
->
item
[
i
])
==
APK_PKG_INSTALLED
)
oldpkg
=
pkg
;
}
}
...
...
@@ -313,39 +416,13 @@ int apk_state_lock_name(struct apk_state *state,
/* First we need to make sure the dependants of the old package
* still have their dependencies ok. */
if
(
oldpkg
!=
NULL
&&
oldpkg
->
name
->
rdepends
!=
NULL
)
{
for
(
i
=
0
;
i
<
name
->
rdepends
->
num
;
i
++
)
{
struct
apk_name
*
name0
=
name
->
rdepends
->
item
[
i
];
for
(
j
=
0
;
j
<
name0
->
pkgs
->
num
;
j
++
)
{
struct
apk_package
*
pkg0
=
name0
->
pkgs
->
item
[
j
];
if
(
apk_pkg_get_state
(
pkg0
)
!=
APK_PKG_INSTALLED
)
continue
;
if
(
pkg0
->
depends
==
NULL
)
continue
;
for
(
k
=
0
;
k
<
pkg0
->
depends
->
num
;
k
++
)
{
if
(
pkg0
->
depends
->
item
[
k
].
name
==
name
)
break
;
}
if
(
k
<
pkg0
->
depends
->
num
)
{
/* FIXME: Try fixing harder */
if
(
newpkg
==
NULL
)
{
struct
apk_dependency
dep
;
dep
=
(
struct
apk_dependency
)
{
.
name
=
name0
,
.
result_mask
=
APK_DEPMASK_CONFLICT
,
};
r
=
apk_state_lock_dependency
(
state
,
&
dep
);
}
else
r
=
apk_state_lock_dependency
(
state
,
&
pkg0
->
depends
->
item
[
k
]);
if
(
r
!=
0
)
return
r
;
}
}
}
if
(
oldpkg
!=
NULL
)
{
r
=
for_each_broken_reverse_depency
(
state
,
name
,
newpkg
==
NULL
?
delete_broken_package
:
reinstall_broken_package
);
if
(
r
!=
0
)
return
r
;
}
/* Check that all other dependencies hold for the new package. */
...
...
@@ -515,6 +592,45 @@ static int cmp_upgrade(struct apk_change *change)
return
0
;
}
static
int
fail_if_something_broke
(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
)
{
return
1
;
}
static
int
apk_state_autoclean
(
struct
apk_state
*
state
,
struct
apk_package
*
pkg
)
{
apk_name_state_t
oldns
;
int
i
,
r
;
if
(
pkg
->
depends
==
NULL
)
return
0
;
for
(
i
=
0
;
i
<
pkg
->
depends
->
num
;
i
++
)
{
struct
apk_name
*
n
=
pkg
->
depends
->
item
[
i
].
name
;
if
(
ns_locked
(
state
->
name
[
n
->
id
]))
continue
;
if
(
n
->
flags
&
APK_NAME_TOPLEVEL
)
continue
;
oldns
=
state
->
name
[
n
->
id
];
state
->
name
[
n
->
id
]
=
ns_from_pkg
(
NULL
);
r
=
for_each_broken_reverse_depency
(
state
,
n
,
fail_if_something_broke
);
state
->
name
[
n
->
id
]
=
oldns
;
if
(
r
==
0
)
{
r
=
apk_state_lock_name
(
state
,
n
,
NULL
);
if
(
r
!=
0
)
return
r
;
}
}
return
0
;
}
int
apk_state_commit
(
struct
apk_state
*
state
,
struct
apk_database
*
db
)
{
...
...
@@ -524,8 +640,11 @@ int apk_state_commit(struct apk_state *state,
/* Count what needs to be done */
memset
(
&
prog
,
0
,
sizeof
(
prog
));
list_for_each_entry
(
change
,
&
state
->
change_list_head
,
change_list
)
list_for_each_entry
(
change
,
&
state
->
change_list_head
,
change_list
)
{
if
(
change
->
newpkg
==
NULL
)
apk_state_autoclean
(
state
,
change
->
oldpkg
);
apk_count_change
(
change
,
&
prog
.
total
);
}
if
(
apk_verbosity
>=
1
)
{
r
=
dump_packages
(
state
,
cmp_remove
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment