2 // Microsoft.TeamFoundation.VersionControl.Client.Workspace
5 // Joel Reed (joelwreed@gmail.com)
7 // Copyright (C) 2007 Joel Reed
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Collections
.Generic
;
35 using System
.Web
.Services
;
36 using Microsoft
.TeamFoundation
.VersionControl
.Common
;
38 namespace Microsoft
.TeamFoundation
.VersionControl
.Client
40 public sealed class Workspace
: IComparable
42 private string comment
;
43 private string computer
;
45 private string ownerName
;
46 private DateTime lastAccessDate
;
47 private WorkingFolder
[] folders
;
48 private VersionControlServer versionControlServer
;
49 internal bool readWriteSetting
;
51 internal Workspace(VersionControlServer versionControlServer
, string name
,
52 string ownerName
, string comment
,
53 WorkingFolder
[] folders
, string computer
)
55 this.versionControlServer
= versionControlServer
;
57 this.ownerName
= ownerName
;
58 this.comment
= comment
;
59 this.folders
= folders
;
60 this.computer
= computer
;
62 readWriteSetting
= Workstation
.Settings
["File.ReadWrite"];
65 internal Workspace(VersionControlServer versionControlServer
,
68 this.versionControlServer
= versionControlServer
;
69 this.name
= info
.Name
;
70 this.ownerName
= info
.OwnerName
;
71 this.comment
= info
.Comment
;
72 this.folders
= new WorkingFolder
[0];
73 this.computer
= info
.Computer
;
75 readWriteSetting
= Workstation
.Settings
["File.ReadWrite"];
78 public int CheckIn(PendingChange
[] changes
, string comment
)
80 if (changes
.Length
== 0) return 0;
82 List
<string> serverItems
= new List
<string>();
83 SortedList
<string, PendingChange
> changesByServerPath
= new SortedList
<string, PendingChange
>();
85 foreach (PendingChange change
in changes
)
87 // upload new or changed files only
88 if ((change
.ItemType
== ItemType
.File
) &&
89 (change
.IsAdd
|| change
.IsEdit
))
91 Repository
.CheckInFile(Name
, OwnerName
, change
);
92 SetFileAttributes(change
.LocalItem
);
95 serverItems
.Add(change
.ServerItem
);
96 changesByServerPath
.Add(change
.ServerItem
, change
);
99 SortedList
<string, bool> undoneServerItems
= new SortedList
<string, bool>();
100 int cset
= Repository
.CheckIn(this, serverItems
.ToArray(), comment
, ref undoneServerItems
);
102 foreach (string undoneItem
in undoneServerItems
.Keys
)
104 PendingChange change
= changesByServerPath
[undoneItem
];
105 VersionControlServer
.OnUndonePendingChange(this, change
);
111 public int CompareTo (object o
)
113 Workspace a
= this, b
= (Workspace
)o
;
115 int r0
= a
.VersionControlServer
.ServerGuid
.CompareTo (b
.VersionControlServer
.ServerGuid
);
116 if (r0
!= 0) return r0
;
118 int r1
= a
.Name
.CompareTo (b
.Name
);
119 if (r1
!= 0) return r1
;
121 int r2
= a
.OwnerName
.CompareTo (b
.OwnerName
);
125 public PendingChange
[] GetPendingChanges()
127 return GetPendingChanges(VersionControlPath
.RootFolder
, RecursionType
.Full
);
130 public PendingChange
[] GetPendingChanges(string item
)
132 return GetPendingChanges(item
, RecursionType
.None
);
135 public PendingChange
[] GetPendingChanges(string item
, RecursionType rtype
)
137 return GetPendingChanges(item
, rtype
, false);
140 public PendingChange
[] GetPendingChanges(string item
, RecursionType rtype
,
141 bool includeDownloadInfo
)
143 string[] items
= new string[1];
145 return GetPendingChanges(items
, rtype
, includeDownloadInfo
);
148 public PendingChange
[] GetPendingChanges(string[] items
, RecursionType rtype
)
150 return GetPendingChanges(items
, rtype
, false);
153 public PendingChange
[] GetPendingChanges(string[] items
, RecursionType rtype
,
154 bool includeDownloadInfo
)
156 List
<ItemSpec
> itemSpecs
= new List
<ItemSpec
>();
157 foreach (string item
in items
)
159 itemSpecs
.Add(new ItemSpec(item
, rtype
));
162 Failure
[] failures
= null;
163 PendingChange
[] changes
= Repository
.QueryPendingSets(Name
, OwnerName
, Name
, OwnerName
,
164 itemSpecs
.ToArray(), includeDownloadInfo
,
166 foreach (Failure failure
in failures
)
168 Console
.WriteLine(failure
.ToString());
176 Repository
.DeleteWorkspace(Name
, OwnerName
);
177 Workstation
.Current
.RemoveCachedWorkspaceInfo(VersionControlServer
.Uri
, Name
);
180 public GetStatus
Get()
182 return Get(VersionSpec
.Latest
, GetOptions
.None
);
185 public GetStatus
Get(VersionSpec versionSpec
, GetOptions options
)
187 GetRequest request
= new GetRequest(versionSpec
);
188 return Get(request
, GetOptions
.None
, null, null);
191 public GetStatus
Get(GetRequest request
, GetOptions options
)
193 return Get(request
, options
, null, null);
196 public GetStatus
Get(GetRequest
[] requests
, GetOptions options
)
198 return Get(requests
, options
, null, null);
201 public GetStatus
Get(GetRequest request
, GetOptions options
,
202 GetFilterCallback filterCallback
, object userData
)
204 GetRequest
[] requests
= new GetRequest
[1];
205 requests
[0] = request
;
206 return Get(requests
, options
, filterCallback
, userData
);
209 public GetStatus
Get (string[] items
, VersionSpec version
,
210 RecursionType recursion
, GetOptions options
)
212 List
<GetRequest
> requests
= new List
<GetRequest
>();
213 foreach (string item
in items
)
215 requests
.Add(new GetRequest(item
, recursion
, version
));
218 return Get(requests
.ToArray(), options
, null, null);
221 public GetStatus
Get(GetRequest
[] requests
, GetOptions options
,
222 GetFilterCallback filterCallback
, object userData
)
224 bool force
= ((GetOptions
.Overwrite
& options
) == GetOptions
.Overwrite
);
225 bool noGet
= false; // not implemented below: ((GetOptions.Preview & options) == GetOptions.Preview);
227 GetOperation
[] getOperations
= Repository
.Get(Name
, OwnerName
, requests
, force
, noGet
);
228 if (null != filterCallback
) filterCallback(this, getOperations
, userData
);
230 UpdateLocalVersionQueue updates
= new UpdateLocalVersionQueue(this);
231 foreach (GetOperation getOperation
in getOperations
)
234 GettingEventArgs args
= new GettingEventArgs(this, getOperation
);
236 // Console.WriteLine(getOperation.ToString());
238 if (getOperation
.DeletionId
!= 0)
240 if ((getOperation
.ItemType
== ItemType
.Folder
)&&
241 (Directory
.Exists(getOperation
.SourceLocalItem
)))
243 UnsetDirectoryAttributes(getOperation
.SourceLocalItem
);
244 Directory
.Delete(getOperation
.SourceLocalItem
, true);
246 else if ((getOperation
.ItemType
== ItemType
.File
)&&
247 (File
.Exists(getOperation
.SourceLocalItem
)))
249 UnsetFileAttributes(getOperation
.SourceLocalItem
);
250 File
.Delete(getOperation
.SourceLocalItem
);
253 else if ((!String
.IsNullOrEmpty(getOperation
.TargetLocalItem
))&&
254 (!String
.IsNullOrEmpty(getOperation
.SourceLocalItem
))&&
255 (getOperation
.SourceLocalItem
!= getOperation
.TargetLocalItem
))
257 uPath
= getOperation
.TargetLocalItem
;
260 File
.Move(getOperation
.SourceLocalItem
, getOperation
.TargetLocalItem
);
264 args
.Status
= OperationStatus
.TargetIsDirectory
;
267 else if (getOperation
.ChangeType
== ChangeType
.None
&&
268 getOperation
.VersionServer
!= 0)
270 uPath
= getOperation
.TargetLocalItem
;
271 string directory
= uPath
;
273 if (getOperation
.ItemType
== ItemType
.File
)
274 directory
= Path
.GetDirectoryName(uPath
);
276 if (!Directory
.Exists(directory
))
277 Directory
.CreateDirectory(directory
);
279 if (getOperation
.ItemType
== ItemType
.File
)
281 DownloadFile
.WriteTo(uPath
, Repository
, getOperation
.ArtifactUri
);
282 SetFileAttributes(uPath
);
286 versionControlServer
.OnDownloading(args
);
287 updates
.QueueUpdate(getOperation
.ItemId
, uPath
, getOperation
.VersionServer
);
291 return new GetStatus(getOperations
.Length
);
294 public ExtendedItem
[][] GetExtendedItems (ItemSpec
[] itemSpecs
,
295 DeletedState deletedState
,
298 return Repository
.QueryItemsExtended(Name
, OwnerName
,
299 itemSpecs
, deletedState
, itemType
);
302 public string GetServerItemForLocalItem(string localItem
)
304 string item
= TryGetServerItemForLocalItem(localItem
);
306 throw new ItemNotMappedException(localItem
);
310 public string GetLocalItemForServerItem(string serverItem
)
312 string item
= TryGetLocalItemForServerItem(serverItem
);
314 throw new ItemNotMappedException(serverItem
);
318 public bool IsLocalPathMapped(string localPath
)
320 foreach (WorkingFolder workingFolder
in Folders
)
322 if (localPath
.StartsWith(workingFolder
.LocalItem
))
329 public bool IsServerPathMapped(string serverPath
)
331 foreach (WorkingFolder workingFolder
in Folders
)
333 if (serverPath
.StartsWith(workingFolder
.ServerItem
))
340 public void Map(string teamProject
, string sourceProject
) {
341 WorkingFolder
[] folders
= new WorkingFolder
[1];
342 folders
[0] = new WorkingFolder(sourceProject
, teamProject
);
343 Update(Name
, OwnerName
, folders
);
346 public int PendAdd(string path
)
348 return PendAdd(path
, false);
351 public int PendAdd(string path
, bool isRecursive
)
353 string[] paths
= new string[1];
355 return PendAdd(paths
, isRecursive
);
358 public int PendAdd(string[] paths
, bool isRecursive
)
360 List
<ChangeRequest
> changes
= new List
<ChangeRequest
>();
362 foreach (string path
in paths
)
364 ItemType itemType
= ItemType
.File
;
365 if (Directory
.Exists(path
)) itemType
= ItemType
.Folder
;
366 changes
.Add(new ChangeRequest(path
, RequestType
.Add
, itemType
));
368 if (!isRecursive
|| itemType
!= ItemType
.Folder
) continue;
370 DirectoryInfo dir
= new DirectoryInfo(path
);
371 FileInfo
[] localFiles
= dir
.GetFiles("*", SearchOption
.AllDirectories
);
373 foreach (FileInfo file
in localFiles
)
374 changes
.Add(new ChangeRequest(file
.FullName
, RequestType
.Add
, ItemType
.File
));
377 if (changes
.Count
== 0) return 0;
379 GetOperation
[] operations
= Repository
.PendChanges(this, changes
.ToArray());
380 return operations
.Length
;
383 public int PendDelete(string path
)
385 return PendDelete(path
, RecursionType
.None
);
388 public int PendDelete(string path
, RecursionType recursionType
)
390 string[] paths
= new string[1];
393 return PendDelete(paths
, recursionType
);
396 public int PendDelete(string[] paths
, RecursionType recursionType
)
398 List
<ChangeRequest
> changes
= new List
<ChangeRequest
>();
399 foreach (string path
in paths
)
401 ItemType itemType
= ItemType
.File
;
402 if (Directory
.Exists(path
)) itemType
= ItemType
.Folder
;
403 changes
.Add(new ChangeRequest(path
, RequestType
.Delete
, itemType
));
406 if (changes
.Count
== 0) return 0;
408 GetOperation
[] operations
= Repository
.PendChanges(this, changes
.ToArray());
409 UpdateLocalVersionQueue updates
= new UpdateLocalVersionQueue(this);
411 // first delete all files
412 foreach (GetOperation operation
in operations
)
414 if (operation
.ItemType
!= ItemType
.File
) continue;
415 if (!File
.Exists(operation
.SourceLocalItem
)) continue;
417 UnsetFileAttributes(operation
.SourceLocalItem
);
418 File
.Delete(operation
.SourceLocalItem
);
419 updates
.QueueUpdate(operation
.ItemId
, null, operation
.VersionServer
);
422 // then any directories
423 foreach (GetOperation operation
in operations
)
425 if (operation
.ItemType
!= ItemType
.Folder
) continue;
426 if (!Directory
.Exists(operation
.SourceLocalItem
)) continue;
428 //DirectoryInfo dir = new DirectoryInfo(operation.SourceLocalItem);
429 //FileInfo[] localFiles = dir.GetFiles("*", SearchOption.AllDirectories);
430 //foreach (FileInfo file in localFiles)
431 // UnsetFileAttributes(file.FullName);
433 Directory
.Delete(operation
.SourceLocalItem
, true);
434 updates
.QueueUpdate(operation
.ItemId
, null, operation
.VersionServer
);
438 return operations
.Length
;
441 public int PendEdit(string path
)
443 // Annotation[] annotations = Repository.QueryAnnotation("ExclusiveCheckout",
445 // foreach (Annotation annotation in annotations)
447 // Console.WriteLine(annotation.ToString());
450 return PendEdit(path
, RecursionType
.None
);
453 public int PendEdit(string path
, RecursionType recursionType
)
455 string[] paths
= new string[1];
458 return PendEdit(paths
, recursionType
);
461 public int PendEdit(string[] paths
, RecursionType recursionType
)
463 List
<ChangeRequest
> changes
= new List
<ChangeRequest
>();
464 foreach (string path
in paths
)
466 changes
.Add(new ChangeRequest(path
, RequestType
.Edit
, ItemType
.File
));
469 if (changes
.Count
== 0) return 0;
471 GetOperation
[] getOperations
= Repository
.PendChanges(this, changes
.ToArray());
472 foreach (GetOperation getOperation
in getOperations
)
474 UnsetFileAttributes(getOperation
.TargetLocalItem
);
477 return getOperations
.Length
;
480 public int PendRename(string oldPath
, string newPath
)
482 string newServerPath
;
483 if (VersionControlPath
.IsServerItem(newPath
)) newServerPath
= GetServerItemForLocalItem(newPath
);
484 else newServerPath
= newPath
;
486 ItemType itemType
= ItemType
.File
;
487 if (Directory
.Exists(oldPath
)) itemType
= ItemType
.Folder
;
489 List
<ChangeRequest
> changes
= new List
<ChangeRequest
>();
490 changes
.Add(new ChangeRequest(oldPath
, newServerPath
, RequestType
.Rename
, itemType
));
492 GetOperation
[] getOperations
= Repository
.PendChanges(this, changes
.ToArray());
494 UpdateLocalVersionQueue updates
= new UpdateLocalVersionQueue(this);
495 foreach (GetOperation getOperation
in getOperations
)
497 if (itemType
== ItemType
.File
)
498 File
.Move(oldPath
, getOperation
.TargetLocalItem
);
500 Directory
.Move(oldPath
, getOperation
.TargetLocalItem
);
502 updates
.QueueUpdate(getOperation
.ItemId
, getOperation
.TargetLocalItem
, getOperation
.VersionServer
);
509 public int SetLock(string path
, LockLevel lockLevel
)
511 return SetLock(path
, lockLevel
, RecursionType
.None
);
514 public int SetLock(string path
, LockLevel lockLevel
, RecursionType recursion
)
516 string[] paths
= new string[1];
518 return SetLock(paths
, lockLevel
, recursion
);
521 public int SetLock(string[] paths
, LockLevel lockLevel
)
523 return SetLock(paths
, lockLevel
, RecursionType
.None
);
526 public int SetLock(string[] paths
, LockLevel lockLevel
, RecursionType recursion
)
528 List
<ChangeRequest
> changes
= new List
<ChangeRequest
>();
530 foreach (string path
in paths
)
532 ItemType itemType
= ItemType
.File
;
533 if (Directory
.Exists(path
)) itemType
= ItemType
.Folder
;
534 changes
.Add(new ChangeRequest(path
, RequestType
.Lock
, itemType
, recursion
, lockLevel
));
537 if (changes
.Count
== 0) return 0;
539 GetOperation
[] operations
= Repository
.PendChanges(this, changes
.ToArray());
540 return operations
.Length
;
543 public void Shelve (Shelveset shelveset
, PendingChange
[] changes
,
544 ShelvingOptions options
)
546 List
<string> serverItems
= new List
<string>();
548 foreach (PendingChange change
in changes
)
550 // upload new or changed files only
551 if ((change
.ItemType
== ItemType
.File
) &&
552 (change
.IsAdd
|| change
.IsEdit
))
554 Repository
.ShelveFile(Name
, OwnerName
, change
);
557 serverItems
.Add(change
.ServerItem
);
560 Repository
.Shelve(this, shelveset
, serverItems
.ToArray(), options
);
563 internal static Workspace
FromXml(Repository repository
, XmlReader reader
)
565 string elementName
= reader
.Name
;
567 string computer
= reader
.GetAttribute("computer");
568 string name
= reader
.GetAttribute("name");
569 string owner
= reader
.GetAttribute("owner");
572 DateTime lastAccessDate
= DateTime
.Now
;
573 List
<WorkingFolder
> folders
= new List
<WorkingFolder
>();
575 while (reader
.Read())
577 if (reader
.NodeType
== XmlNodeType
.EndElement
&& reader
.Name
== elementName
)
580 if (reader
.NodeType
== XmlNodeType
.Element
)
584 case "WorkingFolder":
585 folders
.Add(WorkingFolder
.FromXml(repository
, reader
));
588 comment
= reader
.ReadString();
590 case "LastAccessDate":
591 lastAccessDate
= reader
.ReadElementContentAsDateTime();
597 Workspace w
= new Workspace(repository
.VersionControlServer
, name
, owner
, comment
, folders
.ToArray(), computer
);
598 w
.lastAccessDate
= lastAccessDate
;
602 internal void ToXml(XmlWriter writer
, string element
)
604 writer
.WriteStartElement(element
);
605 writer
.WriteAttributeString("computer", Computer
);
606 writer
.WriteAttributeString("name", Name
);
607 writer
.WriteAttributeString("owner", OwnerName
);
608 writer
.WriteElementString("Comment", Comment
);
612 writer
.WriteStartElement("Folders");
614 foreach (WorkingFolder folder
in folders
)
616 folder
.ToXml(writer
, element
);
619 writer
.WriteEndElement();
622 writer
.WriteEndElement();
625 public override string ToString()
627 StringBuilder sb
= new StringBuilder();
629 sb
.Append("Workspace instance ");
630 sb
.Append(GetHashCode());
632 sb
.Append("\n Comment: ");
635 sb
.Append("\n LastAccessDate: ");
636 sb
.Append(LastAccessDate
);
638 sb
.Append("\n Folders: ");
641 foreach (WorkingFolder folder
in folders
)
643 sb
.Append(folder
.ToString());
647 sb
.Append("\n Computer: ");
650 sb
.Append("\n Name: ");
653 sb
.Append("\n OwnerName: ");
654 sb
.Append(OwnerName
);
656 return sb
.ToString();
659 public string TryGetServerItemForLocalItem(string localItem
)
661 string serverItem
= null;
664 // find the longest matching serveritem
665 foreach (WorkingFolder folder
in folders
)
667 //Console.WriteLine("item: {0} =? folder: {1}", localItem, folder.LocalItem);
668 if (!localItem
.StartsWith(folder
.LocalItem
, StringComparison
.InvariantCultureIgnoreCase
)) continue;
670 int clen
= folder
.LocalItem
.Length
;
673 serverItem
= String
.Format("{0}{1}", folder
.ServerItem
, localItem
.Substring(clen
));
681 public string TryGetLocalItemForServerItem(string serverItem
)
683 string localItem
= null;
686 foreach (WorkingFolder folder
in folders
)
688 if (!serverItem
.StartsWith(folder
.ServerItem
, StringComparison
.InvariantCultureIgnoreCase
)) continue;
690 int clen
= folder
.ServerItem
.Length
;
693 localItem
= String
.Format("{0}{1}", folder
.LocalItem
, serverItem
.Substring(clen
));
701 public WorkingFolder
TryGetWorkingFolderForServerItem(string serverItem
)
704 WorkingFolder workingFolder
= null;
706 foreach (WorkingFolder folder
in folders
)
708 if (!serverItem
.StartsWith(folder
.ServerItem
, StringComparison
.InvariantCultureIgnoreCase
)) continue;
710 if (folder
.LocalItem
.Length
> maxPath
)
712 workingFolder
= folder
;
713 maxPath
= folder
.LocalItem
.Length
;
717 return workingFolder
;
720 public int Undo(string path
)
722 return Undo(path
, RecursionType
.None
);
725 public int Undo(string path
, RecursionType recursionType
)
727 string[] paths
= new string[1];
729 return Undo(paths
, recursionType
);
732 public int Undo(string[] paths
, RecursionType recursionType
)
734 List
<ItemSpec
> specs
= new List
<ItemSpec
>();
736 foreach (string path
in paths
)
738 specs
.Add(new ItemSpec(path
, recursionType
));
741 // is this the same logic as a workspace Get?
742 // can we make one function to handle both cases?
744 GetOperation
[] getOperations
= Repository
.UndoPendingChanges(Name
, OwnerName
, specs
.ToArray());
745 foreach (GetOperation getOperation
in getOperations
)
747 if (getOperation
.ChangeType
== ChangeType
.Edit
||
748 getOperation
.ChangeType
== ChangeType
.Delete
)
750 string uPath
= getOperation
.TargetLocalItem
;
751 string directory
= uPath
;
753 if (getOperation
.ItemType
== ItemType
.File
)
754 directory
= Path
.GetDirectoryName(uPath
);
756 if (!Directory
.Exists(directory
))
757 Directory
.CreateDirectory(directory
);
759 if (getOperation
.ItemType
== ItemType
.File
)
761 DownloadFile
.WriteTo(uPath
, Repository
, getOperation
.ArtifactUri
);
762 SetFileAttributes(uPath
);
767 return getOperations
.Length
;
770 public void Update (string newName
, string newComment
, WorkingFolder
[] newMappings
)
772 Workspace w1
= new Workspace(VersionControlServer
, newName
, OwnerName
,
773 newComment
, newMappings
, Computer
);
774 Workspace w2
= Repository
.UpdateWorkspace(Name
, OwnerName
, w1
);
776 Workstation
.Current
.UpdateCachedWorkspaceInfo(VersionControlServer
.Uri
,
779 folders
= w2
.Folders
;
782 public void RefreshMappings ()
784 Workspace w
= Repository
.QueryWorkspace(Name
, OwnerName
);
785 this.folders
= w
.folders
;
788 public string Comment
790 get { return comment; }
793 public string Computer
795 get { return computer; }
798 public WorkingFolder
[] Folders
800 get { return folders; }
808 public DateTime LastAccessDate
810 get { return lastAccessDate; }
813 public string OwnerName
815 get { return ownerName; }
818 public VersionControlServer VersionControlServer
820 get { return versionControlServer; }
823 internal Repository Repository
825 get { return versionControlServer.Repository; }
828 internal void SetFileAttributes(string path
)
830 if (!readWriteSetting
)
831 File
.SetAttributes(path
, FileAttributes
.ReadOnly
);
834 internal void UnsetFileAttributes(string path
)
836 if (!readWriteSetting
)
837 File
.SetAttributes(path
, FileAttributes
.Normal
);
840 internal void UnsetDirectoryAttributes(string path
)
842 if (readWriteSetting
) return;
844 DirectoryInfo dir
= new DirectoryInfo(path
);
845 FileInfo
[] localFiles
= dir
.GetFiles("*", SearchOption
.AllDirectories
);
846 foreach (FileInfo file
in localFiles
)
847 File
.SetAttributes(file
.FullName
, FileAttributes
.Normal
);