StarTeamからSVNぞのプロゞェクトの移行

良い䞀日



StarTeamずは䜕人の人が聞いおいたすか 数ヶ月前の私のように、他の事柄ではほずんど人はいないず思いたす。



私の珟圚の仕事堎たで、そのようなボヌランド補品のこずは聞いたこずがありたせんでした。 Googleに聞いおみるず、この補品はただ存圚し、開発䞭であるこずもわかりたすが、ご想像のずおり、最新バヌゞョンからは遠く、最埌から2番目のバヌゞョンでもありたせん。 2003幎に開発されたバヌゞョン5.3があり、2004幎にここにむンストヌルされお流通したした。 そしお、ほが11幎間、圌女は仕事をしお解決したした。



むニシアチブの専門家ずしお、この叀いモンスタヌの髪の毛はすぐに動き始め、より珟代的なものに移行するこずが決定されたした。これはSVNたたはGitです。 私は圌ず同僚ずの経隓があり、経営陣はすべおに同意したため、遞択はSVNにかかっおいたした。 既補の゜リュヌションを探した結果、 PalarionからSVNのImporterが 生たれたした。この゜リュヌションでは、ハブに関する蚘事もありたす。 しかし、結局のずころ、すべおが単玔すぎるわけではなく、バヌゞョン5.3があり、この補品には2005バヌゞョンのSDKが必芁であり、非垞に問題が倚いこずが刀明したした。 必芁なラむブラリの名前を倉曎するなど、あらゆる皮類のトリックを䜿甚しおも、このむンポヌタヌを起動できたせんでした。



他に䜕ができたすか 次のように、新しいStarTeamサヌバヌを䜜成しようずしたした。 SVNず統合され、既存のサヌバヌに接続したすが、どうやらお互いに互換性がなく、サヌバヌがお互いを認識しなかったため、䜕もできたせんでした。



それで私は䜕をしたしたか もちろん、私は本圓のプログラマヌずしお行動したした。自分のツヌルを曞きたした



蚭蚈



それでは、゜ヌスデヌタには䜕が含たれおいたすか 私が持っおいる

  1. StarTeam Server 5.3
  2. StarTeam Client 5.3
  3. StarTeam SDK 5.3
  4. 特定のリポゞトリを持぀SVNサヌバヌ
  5. コン゜ヌルクラむアントがむンストヌルされたTortoiseSVN
  6. 譲枡するプロゞェクト




StarTeamの玹介



最新のStarTeamがどのように機胜するかはわかりたせんが、バヌゞョン管理などの機胜がないため、珟圚のバヌゞョンはひどいものです。 各ファむルは個別にバヌゞョン管理されたす。このファむルず同時に配眮されたものを理解し、しばらくスナップショットを匕き出すこずは非珟実的です。 たあ、他のすべおに-このバヌゞョンは、どのファむルが倉曎されおいるかを垞に適切に理解するこずはできたせん぀たり、倉曎されたファむルは100衚瀺されたすが、50/50に觊れなかったファむルは倉曎されたず理解されたす。



たた最近、ロシア語のすべおのコメントずナヌザヌ名がセット「?????」の圢匏で衚瀺されるずいう問題もありたした。これは、゚ンコヌドがどこかに流れおいるこずを意味したすさらに興味深いこずに、゚ンコヌドはクラむアントのどこにも指定されおいたせん そしお、なぜ誰もその理由を確実に知りたせん。そしお、そのような問題が始たったずき、圌らは確実に蚀うこずもできたせん。



StarTeamのその他の構成芁玠は䜕ですか MS SQL 2008に基づくデヌタベヌスから。ク゚リを正しく蚘述し、必芁なものをすべお匕き出すこずができるように思えたすよね。 しかし、S01、S02、Viewセットなどの名前のテヌブルを玄100個芋たため、デヌタベヌスでの盎接ク゚リ䞭の゚ンコヌドが正しく衚瀺されないため、これらすべおを凊理しないこずにしたした。



行動蚈画



そのため、興味深いリポゞトリに゜ヌスプロゞェクトがあり、空のタヌゲットリポゞトリがありたす。 このプロゞェクトでは、 PalarionにSDKに含たれおいるstarteam80.jarが必芁ですが、SDKにはstarteam53.jarしかありたせん。 すぐに蚀っおおきたすが、このプロゞェクトの開始前にJavaでプログラムを䜜成したこずはなく、1行のコヌドでした。 ただし、必芁な堎合は、IDEをむンストヌルしお詊しおください。 IDEずしおNetBeansを遞択し、starteam53.jarの䞭身を解析し始めたした。

このパッケヌゞ内には、StarTeamサヌバヌを操䜜できるクラスのセットがすべお含たれおいたす。 BorlandサむトにはSDKのドキュメントがあり、膚倧な数のクラスで無意味なリヌルからあなたを救いたす。 次に、サヌバヌに接続しおプロゞェクトのリストを返すこずができる単玔なプロゞェクトを䜜成したす。 StarTeamのラむブラリを2時間苊しめた埌、私は望たしい結果を達成したした。 SDKを䜿甚しおStarTeamを操䜜できるこずが明らかになったため、ストヌリヌ党䜓を転送する方法を決定するだけで枈みたす。



しかし それでは、StarTeamのすべおの問題に぀いおストヌリヌをどのように再配眮したすか



StarTeamには、各ファむルのタむムスタンプがありたす。 コメント付きの個々のファむルの倉曎履歎ず倉曎の正確な時間を取埗できたす。これは、これに基づいお構築するこずを意味したす。



StarTeamでコミットが行われるず、コミット䞭の各ファむルにコメントが曞き蟌たれるため、最初のファむルからコメントず䜜成者を取埗するだけで十分で、残りはすでに䞀臎しおいたす。



StarTeamにはファむルを保存する機胜があり、プロゞェクトに保存したす。プロゞェクトにはファむルずフォルダヌがあり、フォルダヌにはさらに倚くのファむルずフォルダヌがあり、各ファむルにはバヌゞョンがありたす。



たた、SDKにファむルを単玔に抜出するように芁求するず、StarTeamはクラむアントでデフォルトで構成されおいる堎所にファむルを抜出したす。これは私にずっおはうたくいかず、最初にファむルストリヌムに抜出する必芁がありたすディスクに。



次の移行パスを思い付きたした。

  1. StarTeamからロヌカルドラむブ䞊のフォルダヌにすべおをアップロヌドしたす。
  2. フォルダを通過しおすべおをSVNにアップロヌドし、コメントフィヌルドにStarTeamでコミットが行われた時刻を入力したす。


次のスキヌムに埓っおアンロヌドしたす。

  1. フォルダツリヌずプロゞェクトファむルの再垰的な走査を開始したす。
  2. 最初のファむルを取埗したす。
  3. 圌の話党䜓を抜出したす。
  4. 履歎を確認し、ファむルをフォルダヌに入れおプロゞェクトを゚クスポヌトしたす。
  5. マスク「yyyy.MM.dd.HH.mm」にタむムスタンプを持぀フォルダヌを䜜成したす最初は1ミリ秒の粟床で実行したしたが、刀明したように、1぀のコミットからのファむルは異なるリビゞョンに入るこずがありたすが、これは間違っおいたす衝突ず問題のアプロヌチはそうではなかった;
  6. フォルダヌに履歎ファむルを䜜成したす。ここには、䜜成者の名前、コメント、タむムスタンプが曞き蟌たれおいたす。
  7. 最埌のファむルが抜出されるたで行いたす。




StarTeamからの抜出



したがっお、NetBeans、Java、およびこのプログラミング蚀語での0の経隓。 Javaの開発経隓がないからずいっお怖くはありたせん。Googleがあるからです。プロゞェクトは䞀床限りであり、誰も私から最高の知識を必芁ずしないので、どこでもコヌドのパフォヌマンス/メモリ/矎しさを犠牲にするこずができたす。



コミットを抜出するずきに、文字列ではなくIDずしおコミットの䜜成者が返されるずいう問題に遭遇したした。 ドキュメントの怜玢では、著者を取埗できるこずが瀺されたしたが、ID +名前のリストの圢匏でしたが、゚ンコヌドに問題があり、倚くのナヌザヌを読むこずができず、䜕らかの理由で倚数のテむクがあり、SVNで耇補を開始する蚈画はありたせんでした。 デヌタベヌスで必芁なビュヌを芋぀け、そこから電子メヌルで陀倖メ゜ッドを䜿甚しお、どの著者がどの著者に属するかを割り圓おたした。 ここに最倧の束葉杖がありたす。著者の名前ず、パスワヌドずナヌザヌをスむッチケヌスを介しお返したしたが、それは愚かで最適ではありたせんが、私の問題には行き先がありたせん。



このプログラミング蚀語での䜜業経隓がないにもかかわらず、私は悪いコヌドを曞く぀もりはなく、次のようになりたした。



StarTeamからデヌタを取埗する゜ヌスコヌド
Server StarTeamServer = new Server("WINAPPSRV", 49201); StarTeamServer.connect(); if (StarTeamServer.isConnected()) { System.out.println("Connect to server OK!"); StarTeamServer.logOn("markov", "123456"); if (StarTeamServer.isLoggedOn()) { System.out.println("LogOn to server OK!"); Project[] projects = StarTeamServer.getProjects(); Project TW = null; for (Project currentproject : projects) { if (currentproject.getName().equals("Tw")) { TW = currentproject; break; } } if (TW != null) { System.out.println("Try to find first revision"); View CurrentView = TW.getDefaultView(); //       /   ExtractFullTreeFromRoot(CurrentView.getRootFolder(), "/", "C:/StarTeamToSVN"); } else { System.out.println("Project Tw not found in StarTeam repository"); } } else { System.out.println("LogOn to server failed :'("); } StarTeamServer.disconnect();
      
      









関数゜ヌスコヌド
 private static void ExtractFileHistory(com.starbase.starteam.File SourceFile, String SourceFolderName, String RootFolder) { Item[] FileHistory = SourceFile.getHistory(); for (Item CurrentHistoryItem : FileHistory) { com.starbase.starteam.File CurrentHistoryFile = (File) CurrentHistoryItem; String FullFileName = RootFolder + "/" + FormatOLEDATEToString(CurrentHistoryFile.getModifiedTime()) + "/Files" + SourceFolderName + CurrentHistoryFile.getName(); String FullPath = RootFolder + "/" + FormatOLEDATEToString(CurrentHistoryFile.getModifiedTime()) + "/Files" + SourceFolderName; String HistoryFileName = RootFolder + "/" + FormatOLEDATEToString(CurrentHistoryFile.getModifiedTime()) +"/@History.txt"; System.out.format("FileName = %s; Revision = %d; CreatedTime = %s; Author = %s; Comment = '%s';%n", FullFileName, CurrentHistoryFile.getRevisionNumber() + 1, FormatOLEDATEToString(CurrentHistoryFile.getModifiedTime()), FindAuthorNameById(CurrentHistoryFile.getModifiedBy()), CurrentHistoryFile.getComment()); FileOutputStream fop = null; java.io.File file; try { java.io.File directory = new java.io.File(FullPath); if (!directory.exists()) { directory.mkdirs(); } file = new java.io.File(FullFileName); fop = new FileOutputStream(file); CurrentHistoryFile.checkoutToStream(fop, com.starbase.starteam.Item.LockType.UNCHANGED, false); fop.flush(); fop.close(); java.io.File HistoryFile = new java.io.File(HistoryFileName); if (!HistoryFile.exists()) { PrintWriter out = new PrintWriter(HistoryFileName); out.println("AuthorID: " + CurrentHistoryFile.getModifiedBy()); out.println("AuthorName: " + FindAuthorNameById(CurrentHistoryFile.getModifiedBy())); out.println("TimeStamp: " + FormatOLEDATEToString(CurrentHistoryFile.getModifiedTime())); out.println("Comment: " + CurrentHistoryFile.getComment()); out.close(); } //System.out.println("Done"); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fop != null) { fop.close(); } } catch (IOException e) { e.printStackTrace(); } } } } private static void ExtractFullTreeFromRoot(com.starbase.starteam.Folder SourceFolder, String SourceFolderName, String RootFolder) { ExtractFilesFromFolder(SourceFolder, SourceFolderName, RootFolder); Item[] RootFolders = SourceFolder.getItems("Folder"); for (Item CurrentItem : RootFolders) { Folder CurrentFolder = (Folder)CurrentItem; ExtractFullTreeFromRoot(CurrentFolder, SourceFolderName+CurrentFolder.getPathFragment()+"/", RootFolder); } } private static void ExtractFilesFromFolder(com.starbase.starteam.Folder SourceFolder, String SourceFolderName, String RootFolder) { Item[] RootFiles = SourceFolder.getItems("File"); for (Item CurrentItem : RootFiles) { com.starbase.starteam.File MyFile = (File) CurrentItem; if (SourceFolderName.isEmpty()) { ExtractFileHistory(MyFile, "/", RootFolder); } else { ExtractFileHistory(MyFile, SourceFolderName, RootFolder); } } } private static String FormatOLEDATEToString(OLEDate SourceValue) { DateFormat formatter = new SimpleDateFormat("yyyy.MM.dd.HH.mm"); return formatter.format(SourceValue.createDate()); }
      
      







私の意芋では、それでもたったく悪い結果にはならなかった。



この抜出スキヌムを䜿甚しお、玄2,000のリビゞョンを取埗したしたが、これは長い間続いおいるプロゞェクトには䞍十分ですが、これはここで受け入れられおいる開発機胜ず゜フトりェア自䜓によるものです。 たた、長い間、抜出したリビゞョンが正しく、正しく分解されおいるかどうかを手動でチェックしたした。



今ではすべおをSVNに正しくコミットするこずが残っおおり、これはすでに最初の段階よりも少し簡単です。



SVNに蚘入



SVNの塗り぀ぶしパタヌンは簡単です。

1フォルダヌの完党なリストを取埗しお䞊べ替えたすフォルダヌに名前を付けるず、これに圹立ちたす。

2欠萜しおいるファむルずフォルダヌのリストを珟圚のリビゞョンのSVNフォルダヌに䜜成したす。

3Filesサブフォルダヌの内容をSVNフォルダヌにコピヌしたす。

4SVNで欠萜しおいるファむルずフォルダヌの堎合、远加したす。

5珟圚のSVNの䜜業コピヌをコミットしたす。



実装䞭に、いく぀かの問題が発生したした。 ぀たり、コミットぞのコメントでは、二重匕甚笊の前にバックスラッシュを配眮しお、匕甚笊が正しく凊理されるようにする必芁がありたす。 たた、@蚘号を含むファむルたたはパスを远加する堎合、svnがファむル名を正しく理解できるように、最埌に別の@を远加する必芁がありたす。 ここで、コヌドが悪化したこずがわかりたした。すぐにやりたかったからです。



ネタバレ芋出し
  //1.    - java.io.File dir = new java.io.File("C:/StarTeamToSVN"); java.io.File[] subDirs = dir.listFiles(new FileFilter() { @Override public boolean accept(java.io.File pathname) { return pathname.isDirectory(); } }); //2.   Arrays.sort(subDirs); //3.         //1.      ,    //2.         SVN //3.   Files        StarTeam  SVN //4.       SVN  //5.        java.io.File RootSVN = new java.io.File("C:\\TestASU"); for (java.io.File CurrentDir : subDirs){ try { ArrayList<java.io.File> MyFiles = new ArrayList<>(); String StarTeamSourceFolder = CurrentDir.getAbsolutePath()+"\\Files\\"; listf(StarTeamSourceFolder, MyFiles); ///String[] SVNAddFiles = new String[](); ArrayList<String> SVNAddFiles = new ArrayList<>(); for (java.io.File CurrentFile: MyFiles) { String FullSourcePath = CurrentFile.getAbsolutePath(); String FullDestPath = "C:\\TestASU\\" + FullSourcePath.substring(FullSourcePath.indexOf(StarTeamSourceFolder) + StarTeamSourceFolder.length()) ; //   ,     java.io.File DestFile = new java.io.File(FullDestPath); java.io.File ParentFolder = DestFile.getParentFile(); while ((ParentFolder != null) && (ParentFolder.compareTo(RootSVN) != 0 )) { if (!ParentFolder.exists()) { SVNAddFiles.add(0, ParentFolder.getAbsolutePath()); } ParentFolder = ParentFolder.getParentFile(); } if (!DestFile.exists()) { SVNAddFiles.add(FullDestPath); } } //       Set<String> s = new LinkedHashSet<>(SVNAddFiles); //  java.io.File RootStarTeam = new java.io.File(StarTeamSourceFolder); try { copyFolder(RootStarTeam, RootSVN); } catch (IOException ex) { Logger.getLogger(StarTeamToSVN.class.getName()).log(Level.SEVERE, null, ex); } Thread.sleep(5000); //  / for (String NewItem: s) { SVNAddFile(NewItem, CurrentDir.getName()); } //    String HistoryPath = CurrentDir.getAbsolutePath() + "\\@History.txt"; String AuthorUserName = ""; String AuthorPassword = ""; String AuthorComment = ""; try { for (String line : Files.readAllLines(Paths.get(HistoryPath), Charset.defaultCharset())) { if (line.contains("AuthorID")) { String AuthorID = line.substring(line.indexOf(": ")+2); AuthorUserName = FindAuthorUserNameByID(Integer.parseInt(AuthorID)); AuthorPassword = FindAuthorPasswordNameByID(Integer.parseInt(AuthorID)); } if (line.contains("TimeStamp")) { AuthorComment = line.substring(line.indexOf(": ")+2); } if (line.contains("Comment")) { AuthorComment = AuthorComment + "\n" + line.substring(line.indexOf(": ")+2); } if (!line.contains(": ")) { AuthorComment = AuthorComment + "\n" + line; } } } catch (IOException ex) { Logger.getLogger(StarTeamToSVN.class.getName()).log(Level.SEVERE, null, ex); } if ((AuthorUserName == "")||(AuthorPassword == "")) { throw new IOException("Ho Authentification data"); } Thread.sleep(1000); SVNCommit("C:\\TestASU\\", CurrentDir.getName(), AuthorUserName, AuthorPassword, AuthorComment); } catch (InterruptedException ex) { Logger.getLogger(StarTeamToSVN.class.getName()).log(Level.SEVERE, null, ex); } }
      
      







ここには時間遅延がありたす.svnにはデヌタベヌスにすべおを远加する時間が垞にあるわけではなく、ファむルがアンチりむルスにずっお興味深いこずがあるため、遞択方法によっおこれらの倀に問題はないこずが刀明したした。 svnでは、svn add FOLDERNAMEを実行するず、コンテンツを含むフォルダヌ党䜓が远加されたすが、プロセスをより正確に制埡するために、フォルダヌずファむルを個別に远加するより正確な方法のように思えたした。



おわりに



この蚘事を曞いおいる間、私のプロゞェクトは完党に移行したした。 IT専門家が叀いテクノロゞヌが䜿甚されおいる堎所に行くこずは珍しくなく、圌らがより珟代的なものに切り替えたいず思っおいるこずを知っおいるので、githubに私のプロゞェクトを投皿したした。 ここにプロゞェクトぞのリンクがありたす 。



たた、Javaプログラミングの経隓も積んだ。 特定のプロゞェクト甚にコヌドを倉曎する必芁がありたすが、完党に機胜し、最小限の改善が必芁です。 たた、異なるバヌゞョンのSDKを䜿甚するバヌゞョンに移行したり、特定のバヌゞョンのSDKに合わせおコヌドを調敎したりするこずもできたす。



誰かがこの蚘事が将来圹に立぀ず思うこずを願っおいたす。



All Articles