diff --git a/autoload/magit/state.vim b/autoload/magit/state.vim
index 170fd2d78bdc6e144dfcb3630dbd154258f5b857..39f2c209ddfd8539ef62efec6b6b68b1d3595183 100644
--- a/autoload/magit/state.vim
+++ b/autoload/magit/state.vim
@@ -1,17 +1,31 @@
-function! magit#state#is_file_visible(section, filename) dict
-	return ( has_key(self.dict[a:section], a:filename) &&
-		 \ ( self.dict[a:section][a:filename].visible == 1 ) )
+function! magit#state#is_file_visible() dict
+	return self.visible
 endfunction
 
-function! magit#state#is_dir(section, filename) dict
-	return ( has_key(self.dict[a:section], a:filename) &&
-		 \ ( self.dict[a:section][a:filename].dir != 0 ) )
+function! magit#state#set_file_visible(val) dict
+	let self.visible = a:val
+endfunction
+
+function! magit#state#toggle_file_visible() dict
+	let self.visible = ( self.visible == 0 ) ? 1 : 0
+endfunction
+
+function! magit#state#is_file_dir() dict
+	return self.dir != 0
 endfunction
 
 function! magit#state#get_files(mode) dict
 	return self.dict[a:mode]
 endfunction
 
+function! magit#state#must_be_added() dict
+	return ( self.empty == 1 ||
+		\ self.symlink != '' ||
+		\ self.dir != 0 ||
+		\ self.binary == 1 )
+endfunction
+
+
 " s:hunk_template: template for hunk object (nested in s:diff_template)
 " WARNING: this variable must be deepcopy()'ied
 let s:hunk_template = {
@@ -37,6 +51,11 @@ let s:file_template = {
 \	'binary': 0,
 \	'symlink': '',
 \	'diff': s:diff_template,
+\	'is_dir': function("magit#state#is_file_dir"),
+\	'is_visible': function("magit#state#is_file_visible"),
+\	'set_visible': function("magit#state#set_file_visible"),
+\	'toggle_visible': function("magit#state#toggle_file_visible"),
+\	'must_be_added': function("magit#state#must_be_added"),
 \}
 
 " magit#state#get_file: function accessor for file
@@ -45,12 +64,13 @@ let s:file_template = {
 " param[in] create: boolean. If 1, non existing file in Dict will be created.
 " if 0, 'file_doesnt_exists' exception will be thrown
 " return: Dict of file
-function! magit#state#get_file(mode, filename, create) dict
+function! magit#state#get_file(mode, filename, ...) dict
 	let file_exists = has_key(self.dict[a:mode], a:filename)
-	if ( file_exists == 0 && a:create == 1 )
+	let create = ( a:0 == 1 ) ? a:1 : 0
+	if ( file_exists == 0 && create == 1 )
 		let self.dict[a:mode][a:filename] = deepcopy(s:file_template)
 		let self.dict[a:mode][a:filename].visible = 0
-	elseif ( file_exists == 0 && a:create == 0 )
+	elseif ( file_exists == 0 && create == 0 )
 		throw 'file_doesnt_exists'
 	endif
 	return self.dict[a:mode][a:filename]
@@ -213,8 +233,6 @@ let magit#state#state = {
 			\ 'get_hunks': function("magit#state#get_hunks"),
 			\ 'get_flat_hunks': function("magit#state#get_flat_hunks"),
 			\ 'add_file': function("magit#state#add_file"),
-			\ 'is_dir': function("magit#state#is_dir"),
-			\ 'is_file_visible': function("magit#state#is_file_visible"),
 			\ 'update': function("magit#state#update"),
 			\ 'dict': { 'staged': {}, 'unstaged': {}},
 			\ }
diff --git a/plugin/magit.vim b/plugin/magit.vim
index 1d1e56ecf61c60d10918f725659ef9f8dbb810f9..30314494705aedff505f3534ea096d7d517199ec 100644
--- a/plugin/magit.vim
+++ b/plugin/magit.vim
@@ -550,9 +550,11 @@ function! magit#open_close_folding(...)
 	" if first param is set, force visible to this value
 	" else, toggle value
 	let file = s:state.get_file(section, filename, 0)
-	let file.visible =
-				\ ( a:0 == 1 ) ? a:1 :
-				\ ( file.visible == 0 ) ? 1 : 0
+	if ( a:0 == 1 )
+		call file.set_visible(a:1)
+	else
+		call file.toggle_visible()
+	endif
 	call magit#update_buffer()
 endfunction
 
@@ -677,8 +679,10 @@ function! s:mg_select_closed_file()
 		let list = matchlist(getline("."), g:magit_file_re)
 		let filename = list[2]
 		let section=<SID>mg_get_section()
-		if ( s:state.is_file_visible(section, filename) == 0 ||
-			\ s:state.is_dir(section, filename) == 1 )
+		
+		let file = s:state.get_file(section, filename)
+		if ( file.is_visible() == 0 ||
+			\ file.is_dir() == 1 )
 			let selection = s:state.get_flat_hunks(section, filename)
 			return selection
 		endif
@@ -700,20 +704,14 @@ function! magit#stage_block(selection, discard) abort
 	let file = s:state.get_file(section, filename, 0)
 	if ( a:discard == 0 )
 		if ( section == 'unstaged' )
-			if ( file.empty == 1 ||
-			\    file.symlink != '' ||
-			\    file.dir != 0 ||
-			\    file.binary == 1 )
+			if ( file.must_be_added() )
 				call magit#utils#system('git add ' .
 					\ magit#utils#add_quotes(filename))
 			else
 				call <SID>mg_git_apply(header, a:selection)
 			endif
 		elseif ( section == 'staged' )
-			if ( file.empty == 1 ||
-			\    file.symlink != '' ||
-			\    file.dir != 0 ||
-			\    file.binary == 1 )
+			if ( file.must_be_added() )
 				call magit#utils#system('git reset ' .
 					\ magit#utils#add_quotes(filename))
 			else
@@ -726,10 +724,7 @@ function! magit#stage_block(selection, discard) abort
 		endif
 	else
 		if ( section == 'unstaged' )
-			if ( file.empty == 1 ||
-			\    file.symlink != '' ||
-			\    file.dir != 0 ||
-			\    file.binary == 1 )
+			if ( file.must_be_added() )
 				call delete(filename)
 			else
 				call <SID>mg_git_unapply(header, a:selection, 'unstaged')